Unity3D 学习笔记 —— Tween对象的实现与动作管理
来源:互联网 发布:linux同名文件夹 编辑:程序博客网 时间:2024/06/05 17:03
Unity3D 学习笔记 —— Tween对象的实现与动作管理
这周的作业我选择做Tween的实现, 一方面觉得挺好玩的(可以拓展原有系统类的方法, 想想就激动。 相当于可以把自己写的一些方法像库一样使用)。另一方面觉得的确有用, 而不是像GUI那样全程看教程或者文档跟着做就完事了(没有贬低的意思)
1. 预备知识
a. C#的拓展方法
C#的拓展方法, 就是提供了一种让我们可以为原有类添加新方法的功能。一个声明拓展方法的Demo如下:
public static class extend_method_test{ //This is Extened Method, The first parameter beging with (this Type name, args) public static bool NextBool(this System.Random random) { return random.NextDouble() > 0.5; }}public class NewBehaviourScript : MonoBehaviour { // Use this for initialization void Start () { System.Random rand = new System.Random(); print (rand.NextBool ()); } // Update is called once per frame void Update () { }}
主要注意以下几点:
1. 拓展方法要放在一个public static class
里面
2. 拓展方法本身应该是静态的, 即包含 static
修饰。
3. 拓展方法参数第一位代表要拓展的对象, 记得一定要用this
修饰之。
4. 拓展方法后面的参数, 代表使用时需要传递的参数。
b. C#协程的使用
教程在这里: http://www.cnblogs.com/vivid-stanley/p/5272736.html
使用协程可以让程序实现类似多线程的效果。
c. 对Tween的了解。
这里当然要上DOTween 的官网:http://dotween.demigiant.com/documentation.php
还有很多,不可能一一实现,挑其中几个就好了。
2. 实现过程
a. 拓展方法的添加。
既然是说拓展方法, 那么先来两个简单的例子:
public static Vector3 GetRGB(this Color color) { return new Vector3 (color.r, color.g, color.b); } public static Color ToColor(this Vector3 vec3) { return new Color (vec3.x, vec3.y, vec3.z); }
这两个方法分别拓展了 Color 和 Vector3 类, 相当于实现了从Vector3和Color的相互转化(取RGB值),这里在
实现 DoColor()
方法时会用到。
然后是实现动作的拓展方法, 以DoMove()
方法的代码为例子(其他的差不多)
public static tween DoMove(this Transform transform, Vector3 target, float time) { MonoBehaviour mono = transform.GetComponents<MonoBehaviour> () [0]; tween myTween = new tween ("DoMove", transform, target, time); Coroutine coroutine = mono.StartCoroutine (mono.UniversalVector3Iter(myTween)); myTween.SetCoroutine (coroutine); return myTween; }
这里拓展方法的参数有两个, 第一个是需要移动到的位置target, 第二个是移动时的总时间。
mono在这里乱入的原因是只有mono类才能启动协程, 所以必须得到一个mono对象。
b. 协程函数的实现
协程函数就是实现运动的部分, 为了避免重复, 我写了一个通用的协程函数(对于Vector3 类型通用)
public static IEnumerator UniversalVector3Iter (this MonoBehaviour mono, tween myTween) { for (; myTween.currentLoop < myTween.loops; myTween.currentLoop++) { myTween.Reset (); Vector3 distance = (myTween.target - myTween.origin) / myTween.time; for (float f = myTween.time; f >= 0.0f; f -= Time.deltaTime) { changeEveryFrame (myTween, distance * Time.deltaTime); yield return null; while (myTween.isPause == true) { yield return null; } } } myTween.OnComplete (); }
然后在changeEveryFrame ()
方法里面确定到底调用哪种方法, 如下:
public static void changeEveryFrame(tween myTween, Vector3 changedValue) { if (myTween.tweenType == "DoMove") { myTween.transform.Translate(changedValue); } if (myTween.tweenType == "DoRotate") { myTween.transform.Rotate (changedValue); } if (myTween.tweenType == "DoScale") { myTween.transform.localScale += changedValue; } if (myTween.tweenType == "DoColor") { myTween.material.color = (myTween.material.color.GetRGB () + changedValue).ToColor (); } if (myTween.tweenType == "DoFade") { Color c = new Color (myTween.material.color.r, myTween.material.color.g, myTween.material.color.b, myTween.material.color.a + changedValue.x); myTween.material.color = c; } }
c. Tween 的实现
Tween我认为就是对这个动作协程管理的工具。代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; using ExtendMethods;public class tween { public string tweenType; public int loops; public int currentLoop; public Transform transform; public Material material; public Vector3 originalPosition; public Vector3 originalRotation; public Vector3 originalScale; public Vector3 origin; public Vector3 target; public float time; public bool isPause; public bool autoKill; public Coroutine coroutine; public delegate void Callback(); public Callback onComplete; public Callback onKill; public Callback onPause; public tween(string type, Transform trans, Vector3 tar, float ti) { tweenType = type; transform = trans; material = trans.GetComponent<MeshRenderer> ().material; target = tar; time = ti; setOrigin (trans); loops = 1; currentLoop = 0; isPause = false; autoKill = true; coroutine = null; onComplete = null; } public void Reset() { if (tweenType == "DoMove") { transform.position = origin; } if (tweenType == "DoRotate") { transform.position = origin; } if (tweenType == "DoScale") { transform.position = origin; } if (tweenType == "DoColor") { material.color = origin.ToColor(); } if (tweenType == "DoFade") { Color c = new Color (material.color.r, material.color.g, material.color.b, origin.x); material.color = c; } } public void setOrigin(Transform transform) { if (tweenType == "DoMove") { origin = transform.position; } if (tweenType == "DoRotate") { origin = transform.rotation.eulerAngles; } if (tweenType == "DoScale") { origin = transform.localScale; } if (tweenType == "DoColor") { origin = material.color.GetRGB(); } if (tweenType == "DoFade") { origin = new Vector3 (material.color.a, 0, 0); } } public tween SetLoops(int l) { loops = l; return this; } public tween SetCoroutine(Coroutine c) { coroutine = c; return this; } public tween SetAutoKill(bool auto) { autoKill = auto; return this; } public tween SetOnComplete(Callback c) { onComplete += c; return this; } public tween SetOnKill(Callback c) { onKill += c; return this; } public tween SetOnPause(Callback c) { onPause += c; return this; } public void Pause() { isPause = true; } public void Play() { isPause = false; } public void Restart() { Reset (); Play (); } public void Complete() { OnComplete (); } public void Kill() { MonoBehaviour mono = transform.GetComponent<MonoBehaviour> (); mono.StopCoroutine (coroutine); } public void OnComplete() { if (onComplete != null) { onComplete (); } if (autoKill) { Kill (); } } public void OnKill() { if (onKill != null) { onKill (); } } public void OnPause() { if (onPause != null) { onPause (); } }}
根据代码可以看到, 我一共实现了5个动作,DoMove(), DoRotate(), DoScale(), DoFade(), DoColor()
d. 效果测试
测试代码如下:
myTween = transform.DoFade (new Vector3 (0.0f, 0f, 0f), 3.0f).SetLoops(3); myTween = transform.DoRotate (new Vector3(150f, 0f, 0f), 3.0f).SetLoops(3);
可以看到两者同时进行, 互不干扰。
其他的测试与此类似。
3. 实验思考
不足之处:
1. if…else 用得比较多, 面向对象思想不够
2. 有些代码用Lambda函数可能更好,更简洁。
3.只实现了动作的并行, 没有实现串行(就是一个接一个的Sequence)
- Unity3D 学习笔记 —— Tween对象的实现与动作管理
- android学习笔记(九)——动画效果的实现1tween动画
- Android学习笔记14:Tween Animation动画的实现
- [ Libgdx 学习笔记 ] - Action 动作类与 Actions(管理类,动作池) [待更新]
- [ Libgdx 学习笔记 ] - Action 动作类与 Actions(管理类,动作池)
- 【Unity3D入门】Unity3D学习笔记001——Unity的下载、安装与破解
- 【Unity3D入门】Unity3D学习笔记002——Visual Studio的下载、安装、破解与配置
- 【unity学习笔记】unity3d- 使用对象池高效管理内存
- Unity3D学习笔记——Unity3D的窗口布局
- 内存管理学习笔记——自定义malloc()与内存池的实现(未完)
- Cosos 学习笔记 ——动作
- Unity3D内存管理——对象池
- Unity3D——对象管理缓冲池
- C++面向对象—成员函数与成员变量的实现机制学习笔记(1)
- Unity3D的学习笔记与资料
- Unity3D学习(4)之分离动作管理器的3D版牧师与魔鬼
- Unity3d学习笔记2——GUI实现简单计算器
- Unity3d学习笔记3——基本运动与旋转
- linux socket编程之多路复用select的例子
- MMU
- [Leetcode]_27 Remove Element
- 剑指offer
- swjtuoj 2380 Knapsack Problem
- Unity3D 学习笔记 —— Tween对象的实现与动作管理
- android 的单例模式
- c++第六次实验-数组的合并
- Unknown host 'android.oa.com'. You may need to adjust the proxy settings in Gradle.
- 用java编写一个计算器
- python基础知识
- Mysql锁机制
- linux shell函数使用
- 使用Lua脚本对pcap文件进行切流操作