Unity3D从入门到放弃(七) ----DoTween的实现
2017-05-09 12:41
1036 查看
Unity3D从入门到放弃(七)
—-DoTween的实现
5.11修改:在Sequence里面新加入了Clear函数,目的是清除Sequence里List中的Tween。作业要求:
请研究 DOTween 网站 http://dotween.demigiant.com/getstarted.php 网页, 它在 Specific settings 中 transform.DoMove 返回 Tween 对象。请实现该对象,实现对动作的持续管理。本次作业要求完成DOTween实现的内容,DOTween网站已经放在上面。下面简介实现思路和具体实现。
实现思路:
观察了网站的DOTween运作并自己操作了一下,我猜测DOTween的运作模式为:创建一个空物体挂在的脚本,然后在该脚本上进行Tweener和Sequence的操作,并对他们进行管理和操作,而静态类DOTween对该脚本的函数进行封装,供用户使用。(新建Tween出现的脚本)
(脚本信息)
Tween的另一个问题是如何修改函数的值,经过查资料,我了解了Tween的To函数通过getter和setter函数实时改变相应的值,因此我新加入了一个委托change,用于通过时间和插值函数,计算相应的中间值。
Tween第三个问题是如何执行,用Coroutine(协程)可以轻松解决这个问题,协程在每一帧自动从yield重新开始,可以代替Update。
根据这三个信息,可以构造简易DOTween了。
具体实现:
1.类结构如下
(其中ExtendClassFunction文件,包含各种静态类,每个静态类包含相应类的扩展函数)
2.代码如下
代码我会贴在下面,也可以从GitHub上下载,链接:我是下载传送门LerpFunction:(插值函数类,半搬运半修改)
/* * 描 述:存放各种插值函数的类 * 作 者:hza * 创建时间:2017/05/07 00:48:02 * 版 本:v 1.0 */ using System.Collections; using System.Collections.Generic; using UnityEngine; namespace My.LerpFunctionSpace { // Lerp函数类型 public enum LerpFunctionType : int { Linear = 0, QuadIn = 1, QuadOut = 2, QuadBoth = 3, CubicIn = 4, CubicOut = 5, CubicBoth = 6, QuintIn = 7, QuintOut = 8, QuintBoth = 9, SineIn = 10, SineOut = 11, SineBoth = 12, ExpoIn = 13, ExpoOut = 14, ExpoBoth = 15, CircIn = 16, CircOut = 17, CircBoth = 18, ElasticIn = 19, ElasticOut = 20, ElasticBoth = 21, BackIn = 22, BackOut = 23, BackBoth = 24, BounceIn = 25, BounceOut = 26, BounceBoth = 27 } /// <summary> /// 用来进行各种线性插值的计算,time必须在0-1之间 /// </summary> public static class LerpFunction { #region 委托和事件数组 public delegate float LFunction(float from, float to, float time); public static LFunction[] lerfs = new LFunction[] { Linear, QuadIn, QuadOut, QuadBoth, CubicIn, CubicOut, CubicBoth, QuintIn, QuintOut, QuintBoth, SineIn, SineOut, SineBoth, ExpoIn, ExpoOut, ExpoBoth, CircIn, CircOut, CircBoth, ElasticIn, ElasticOut, ElasticBoth, BackIn, BackOut, BackBoth, BounceIn, BounceOut, BounceBoth }; #endregion #region 私有Lerp函数 // 线性 public static float Linear(float from, float to, float time) { return from + (to - from) * time; } // 2次方程 public static float QuadIn(float from, float to, float time) { return from + (to - from) * time * time; } public static float QuadOut(float from, float to, float time) { return from + (to - from) * time * (2f - time); } public static float QuadBoth(float from, float to, float time) { return time < 0.5f ? QuadIn(from, (from + to) / 2, time * 2) : QuadOut((from + to) / 2, to, 2 * time - 1f); } // 3次方程 public static float CubicIn(float 1c6f4 from, float to, float time) { return from + (to - from) * Mathf.Pow(time, 3f); } public static float CubicOut(float from, float to, float time) { return from + (to - from) * (Mathf.Pow(time - 1, 3f) + 1.0f); } public static float CubicBoth(float from, float to, float time) { return time < 0.5f ? CubicIn(from, (from + to) / 2, time * 2) : CubicOut((from + to) / 2, to, 2 * time - 1f); } // 5次方程 public static float QuintIn(float from, float to, float time) { return from + (to - from) * Mathf.Pow(time, 5f); } public static float QuintOut(float from, float to, float time) { return from + (to - from) * (Mathf.Pow(time - 1, 5f) + 1.0f); } public static float QuintBoth(float from, float to, float time) { return time < 0.5f ? QuintIn(from, (from + to) / 2, time * 2) : QuintOut((from + to) / 2, to, 2 * time - 1f); } // 正弦曲线 public static float SineIn(float from, float to, float time) { return from + (to - from) * (1.0f - Mathf.Cos(time * Mathf.PI / 2)); } public static float SineOut(float from, float to, float time) { return from + (to - from) * Mathf.Sin(time * Mathf.PI / 2); } public static float SineBoth(float from, float to, float time) { return time < 0.5f ? SineIn(from, (from + to) / 2, time * 2) : SineOut((from + to) / 2, to, 2 * time - 1f); } // 指数增长 public static float ExpoIn(float from, float to, float time) { return time == 0.0f ? from : from + (to - from) * Mathf.Pow(2f, 10f * (time - 1f)); } public static float ExpoOut(float from, float to, float time) { return time == 1.0f ? to : from + (to - from) * (1f - Mathf.Pow(2f, -10f * time)); } public static float ExpoBoth(float from, float to, float time) { return time < 0.5f ? ExpoIn(from, (from + to) / 2, time * 2) : ExpoOut((from + to) / 2, to, 2 * time - 1f); } // 圆周弧线 static float CircIn(float from, float to, float time) { return from + (to - from) * (1.0f - Mathf.Sqrt(1f - time * time)); } static float CircOut(float from, float to, float time) { return from + (to - from) * Mathf.Sqrt((2f - time) * time); } static float CircBoth(float from, float to, float time) { return time < 0.5f ? CircIn(from, (from + to) / 2, time * 2) : CircOut((from + to) / 2, to, 2 * time - 1f); } // 弹性弧线 public static float ElasticIn(float from, float to, float time) { if (time == 0.0f) return from; if (time == 1.0f) return to; return from + (to - from) * -Mathf.Pow(2.0f, 10.0f * time - 10.0f) * Mathf.Sin((3.33f * time - 3.58f) * Mathf.PI * 2); } public static float ElasticOut(float from, float to, float time) { if (time == 0.0f) return from; if (time == 1.0f) return to; return from + (to - from) * (Mathf.Pow(2.0f, -10.0f * time) * Mathf.Sin((3.33f * time - 0.25f) * Mathf.PI * 2) + 1.0f); } public static float ElasticBoth(float from, float to, float time) { return time < 0.5f ? ElasticIn(from, (from + to) / 2, time * 2) : ElasticOut((from + to) / 2, to, 2 * time - 1f); } // back曲线 public static float BackIn(float from, float to, float time) { return from + (to - from) * time * time * (2.70158f * time - 1.70158f); } public static float BackOut(float from, float to, float time) { return from + (to - from) * (Mathf.Pow(time - 1, 2f) * (2.70158f * time - 1f) + 1.0f); } public static float BackBoth(float from, float to, float time) { return time < 0.5f ? BackIn(from, (from + to) / 2, time * 2) : BackOut((from + to) / 2, to, 2 * time - 1f); } // 弹性曲线 public static float BounceOut(float from, float to, float time) { if (time < 0.363636f) return from + (to - from) * 7.5625f * time * time; else if (time < 0.72727f) { time -= 0.545454f; return from + (to - from) * (7.5625f * time * time + 0.75f); } else if (time < 0.909091f) { time -= 0.818182f; return from + (to - from) * (7.5625f * time * time + 0.9375f); } else { time -= 0.954545f; return from + (to - from) * (7.5625f * time * time + 0.984375f); } } public static float BounceIn(float from, float to, float time) { if (time > 0.636364f) { time = 1.0f - time; return from + (to - from) * (1.0f - 7.5625f * time * time); } else if (time > 0.27273f) { time = 0.454546f - time; return from + (to - from) * (0.25f - 7.5625f * time * time); } else if (time > 0.090909f) { time = 0.181818f - time; return from + (to - from) * (0.0625f - 7.5625f * time * time); } else { time = 0.045455f - time; return from + (to - from) * (0.015625f - 7.5625f * time * time); } } public static float BounceBoth(float from, float to, float time) { return time < 0.5f ? BounceIn(from, (from + to) / 2, time * 2) : BounceOut((from + to) / 2, to, 2 * time - 1f); } #endregion } }
ExpendClassFuntion:
/* * 描 述:用于各种控件,展示扩展函数,进行链式调用 * 作 者:hza * 创建时间:2017/05/08 23:09:03 * 版 本:v 1.0 */ using My.LerpFunctionSpace; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace My.DoTween.Core { public static class TweenClassFunction { // 设置前置函数 public static T OnStart<T>(this T tween, TweenCallBack _callfore) where T : Tween { tween.callfore = _callfore; return tween; } // 设置回调函数 public static T OnComplete<T>(this T tween, TweenCallBack _callback) where T : Tween { tween.callback = _callback; return tween; } // 设置循环次数,如果循环次数<=0,无限循环 public static T SetLoopTime<T>(this T tween, int looptime) where T : Tween { if (looptime < 0) looptime = 0; tween.loopTime = looptime; return tween; } // 暂停动作 public static T Pause<T>(this T tween) where T : Tween { tween.pause = true; return tween; } // 停止动作 public static T Stop<T>(this T tween) where T : Tween { tween.stop = true; return tween; } } public static class TweenerClassFunction { // tweener // 是否在队列内 public static bool isInQueue<T>(this T tweener) where T : Tweener { return tweener.isInqueue; } // 设置差值种类 public static T SetEaseType<T>(this T tweener, LerpFunctionType type) where T : Tweener { tweener.lerptype = type; return tweener; } } public static class SequenceClassFunction { // sequence // 后面添加新节点 public static T Append<T>(this T sequence, Tweener tweener) where T : Sequence { MyDoTween.DeleteCoroutineAndTween(tweener); tweener.isInqueue = true; sequence.tweenActions.Add(tweener); return sequence; } // 在后面添加新的回调函数 public static T AppendCallback<T>(this T sequence, TweenCallBack callback) where T : Sequence { sequence.tweenActions.Add(callback); return sequence; } // 在后面添加新的等待时间 public static T AppendInterval<T>(this T sequence, float time) where T : Sequence { return sequence.Append(MyDoTween.To(() => time, x => time = x, 0, time)); } // 前面添加新节点 public static T Prepend<T>(this T sequence, Tweener tweener) where T : Sequence { MyDoTween.DeleteCoroutineAndTween(tweener); tweener.isInqueue = true; sequence.tweenActions.Insert(0, tweener); return sequence; } // 在前面添加新的回调函数 public static T PrependCallback<T>(this T sequence, TweenCallBack callback) where T : Sequence { sequence.tweenActions.Insert(0, callback); return sequence; } // 在前面添加新的等待时间 public static T PrependInterval<T>(this T sequence, float time) where T : Sequence { return sequence.Prepend(MyDoTween.To(() => time, x => time = x, 0, time)); } // 任意位置添加新节点 public static T Insert<T>(this T sequence, int atPos, Tweener tweener) where T : Sequence { if (atPos > 0 && atPos < sequence.tweenActions.Count) { MyDoTween.DeleteCoroutineAndTween(tweener); tweener.isInqueue = true; sequence.tweenActions.Insert(atPos, tweener); } return sequence; } // 任意位置添加新的回调函数 public static T InsertCallback<T>(this T sequence, int atPos, TweenCallBack callback) where T : Sequence { if (atPos > 0 && atPos < sequence.tweenActions.Count) sequence.tweenActions.Insert(atPos, callback); return sequence; } } public static class TransformClassFunction { // transform public static Tweener DOMove(this Transform transform, Vector3 to, float duration) { return MyDoTween.To(() => transform.position, x => transform.position = x, to, duration); } public static Tweener DOMoveX(this Transform transform, float to, float duration) { MyGetter<float> getter = () => { return transform.position.x; }; MySetter<float> setter = x => { transform.position = new Vector3(x, transform.position.y, transform.position.z); }; return MyDoTween.To(getter, setter, to, duration); } public static Tweener DOMoveY(this Transform transform, float to, float duration) { MyGetter<float> getter = () => { return transform.position.y; }; MySetter<float> setter = y => { transform.position = new Vector3(transform.position.x, y, transform.position.z); }; return MyDoTween.To(getter, setter, to, duration); } public static Tweener DOMoveZ(this Transform transform, float to, float duration) { MyGetter<float> getter = () => { return transform.position.z; }; MySetter<float> setter = z => { transform.position = new Vector3(transform.position.x, transform.position.y, z); }; return MyDoTween.To(getter, setter, to, duration); } public static Tweener DORotate(this Transform transform, Vector3 to, float duration) { return MyDoTween.To(() => transform.eulerAngles, x => transform.eulerAngles = x, to, duration); } public static Tweener DORotateQuaternion(this Transform transform, Quaternion to, float duration) { return MyDoTween.To(() => transform.rotation, x => transform.rotation = x, to, duration); } public static Tweener DOLocalRotate(this Transform transform, Vector3 to, float duration) { return MyDoTween.To(() => transform.localEulerAngles, x => transform.localEulerAngles = x, to, duration); } public static Tweener DOLocalRotateQuaternion(this Transform transform, Quaternion to, float duration) { return MyDoTween.To(() => transform.localRotation, x => transform.localRotation = x, to, duration); } public static Tweener DOScale(this Transform transform, Vector3 to, float duration) { return MyDoTween.To(() => transform.localScale, x => transform.localScale = x, to, duration); } public static Tweener DOScale(this Transform transform, float to, float duration) { return transform.DOScale(transform.localScale * to, duration); } } public static class MaterialClassFunction { // material public static Tweener DOColor(this Material material, Color to, float duration) { return MyDoTween.To(() => material.color, x => material.color = x, to, duration); } } }
MyTweenCore:(保存Tween类和他的子类)
其中关于in和out关键字可以点我
/* * 描 述:实现Tween,Tweener,Tweener<T>和Sequence类,用于实现基本动作类 * 作 者:hza * 创建时间:2017/05/07 12:59:33 * 版 本:v 1.0 */ using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using My.LerpFunctionSpace; using UnityEditor; namespace My.DoTween.Core { // get模板委托 public delegate T MyGetter<out T>(); // set模板委托 public delegate void MySetter<in T>(T value); // 回调委托 public delegate void TweenCallBack(Tween tween, object data); /// <summary> /// 一切动作的基类,扩展Tweener和Sequence /// </summary> public abstract class Tween { public object id; // Tween的标识,要进行动作的主体 public object userData; // 用户信息,用于回调函数 public bool pause; // 暂停 public bool stop; // 停止 public bool isBegin; //动作是否开始 public int loopTime; // 动作循环次数 public TweenCallBack callfore; // 前置函数 public TweenCallBack callback; // 回调函数 // 空构造函数 protected Tween() {} public virtual void Clear() { id = null; userData = null; callfore = null; callback = null; } // update函数模板 public abstract void Update(float dt); } /// <summary> /// Tween的向上继承,保存各种函数,真正的动作基类 /// </summary> public abstract class Tweener : Tween { public float curTime; // 当前时间 public float duration; // 动作持续时间 public LerpFunctionType lerptype; // 插值种类 public bool isInqueue; // 是否在Sequence里面 public abstract Tweener From(); } /// <summary> /// 模板类,用于储存各种模板事件 /// </summary> /// <typeparam name="T"></typeparam> public class Tweener<T> : Tweener { public MyGetter<T> getter; // 起始位置的getter public MySetter<T> setter; // 起始位置的setter public T begValue; // 起始位置 public T endValue; // 目标位置 public ChangeValue change; // 改变T的值 // time范围为0-1 public delegate T ChangeValue(T from, T to, float time); // 构造函数 public static Tweener<T> Create(MyGetter<T> getter, MySetter<T> setter, T endValue, float duration) { Tweener<T> tweener = new Tweener<T>(); // Tween tweener.id = MyDoTween.GetUniqueTweenerID(); tweener.userData = getter(); tweener.pause = false; tweener.stop = false; tweener.isBegin = false; tweener.loopTime = 1; tweener.callfore = null; tweener.callback = null; // Tweener tweener.duration = duration; tweener.isInqueue = false; tweener.curTime = 0; tweener.lerptype = 0; // tweener<T> tweener.getter = getter; tweener.setter = setter; tweener.begValue = getter(); tweener.endValue = endValue; return tweener; } // 使动作反转 public override Tweener From() { // from仅仅建立在动作未开始时 if (!isBegin) { // 目标互换 setter(endValue); endValue = begValue; begValue = getter(); } return this; } public override void Update(float dt) { // 表示动作开始 if (!isBegin) { if (callfore != null) callfore(this, userData); // 更新物体位置 begValue = getter(); isBegin = true; } if (curTime < duration) { if (curTime + dt >= duration) { // 如果达到目标值,设置最终地点 setter(endValue); if (--loopTime == 0) { if (callback != null) callback(this, userData); stop = true; } else { curTime = 0; setter(begValue); } return; } // 设置属性值 setter(change(begValue, endValue, curTime / duration)); // 增加时间 curTime += dt; } } } /// <summary> /// 序列类,用于动作的连续进行 /// </summary> public class Sequence : Tween { public List<object> tweenActions; // 动作,函数队列 public int currentObjectIndex; // 当前动作位置 public object currentObject; // 当前动作,或函数 // 空构造函数 public static Sequence create() { Sequence sequence = new Sequence(); sequence.id = MyDoTween.GetUniqueSequenceID(); sequence.userData = null; sequence.pause = false; sequence.stop = false; sequence.isBegin = false; sequence.loopTime = 1; sequence.callfore = null; sequence.callback = null; sequence.tweenActions = new List<object>(); sequence.currentObjectIndex = 0; sequence.currentObject = null; return sequence; } public override void Clear() { // 基类调用 base.Clear(); // 清除列表内的Tween foreach (object tween in tweenActions) if (tween is Tween) ((Tween)tween).Clear(); } public override void Update(float dt) { // 表示动作开始 if (!isBegin) { if (callfore != null) callfore(this, userData); isBegin = true; } // 如果暂停,返回 if (pause) return; // 在列表内 if (currentObjectIndex >= 0 && currentObjectIndex < tweenActions.Count) { // 设置当前Object if (currentObject == null) currentObject = tweenActions[currentObjectIndex]; // 判断Object种类 if (currentObject is Tween) { Tweener currentAction = (Tweener)currentObject; // 动作完成 if (currentAction.stop) { currentObject = null; currentObjectIndex++; return; } // 动作暂停 if (currentAction.pause) return; // 执行动作 currentAction.Update(dt); } else { TweenCallBack callback = (TweenCallBack)currentObject; currentObject = null; currentObjectIndex++; callback(this, this.userData); } } // 动作执行完成 else if (currentObjectIndex >= tweenActions.Count) { if (--loopTime == 0) { if (callback != null) callback(this, userData); stop = true; } else { foreach (Tweener tweener in tweenActions) { tweener.stop = false; tweener.curTime = 0; } currentObjectIndex = 0; } } } } }
MyDoTween:
/* * 描 述:实现DoTween静态类 * 作 者:hza * 创建时间:2017/05/07 24:29:03 * 版 本:v 1.0 */ using System.Collections; using System.Collections.Generic; using UnityEngine; using My.LerpFunctionSpace; using My.DoTween.Core; using System; namespace My.DoTween { public static class MyDoTween { // 自动执行 public static bool StartAuto = true; private static bool isBegin = false; // tweener容量 public static int TweenerMaxSize = 100; // sequence容量 public static int SequenceMaxSize = 30; public static void Init(bool startAuto, int tweenerSize = 100, int sequenceSize = 30) { // 如果未启动,修改变量 if (!isBegin) { StartAuto = startAuto; TweenerMaxSize = tweenerSize; SequenceMaxSize = sequenceSize; } } // 创建新Sequence public static Sequence Sequence() { Sequence se = My.DoTween.Core.Sequence.create(); AddCoroutineAndTween(se); return se; } public static object GetUniqueTweenerID() { // 当新建Tween时,不允许修改条件 isBegin = true; if (TweenerMaxSize == 0) throw new KeyNotFoundException("Tween超出数量限制"); TweenerMaxSize--; return "Tweener" + Guid.NewGuid(); } public static Tween FreeTweener(Tween tween) { tween.Clear(); tween = null; TweenerMaxSize++; return tween; } public static object GetUniqueSequenceID() { // 当新建Tween时,不允许修改条件 isBegin = true; if (SequenceMaxSize == 0) throw new KeyNotFoundException("Sequence超出数量限制"); SequenceMaxSize--; return "Sequence" + Guid.NewGuid(); } public static Tween FreeSequence(Tween tween) { tween.Clear(); tween = null; SequenceMaxSize++; return tween; } #region To重载 public static Tweener To(MyGetter<float> getter, MySetter<float> setter, float endValue, float duration) { // 设置属性 Tweener<float> newTweener = Tweener<float>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return LerpFunction.lerfs[(int)newTweener.lerptype](from, to, time); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<double> getter, MySetter<double> setter, double endValue, float duration) { // 设置属性 Tweener<double> newTweener = Tweener<double>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return from + (to - from) * LerpFunction.lerfs[(int)newTweener.lerptype](0, 1, time); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<int> getter, MySetter<int> setter, int endValue, float duration) { // 设置属性 Tweener<int> newTweener = Tweener<int>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { // 四舍五入 return from + (int)((to - from) * LerpFunction.lerfs[(int)newTweener.lerptype](0, 1, time) + 0.5); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<Vector2> getter, MySetter<Vector2> setter, Vector2 endValue, float duration) { // 设置属性 Tweener<Vector2> newTweener = Tweener<Vector2>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return from + (to - from) * LerpFunction.lerfs[(int)newTweener.lerptype](0, 1, time); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<Vector3> getter, MySetter<Vector3> setter, Vector3 endValue, float duration) { // 设置属性 Tweener<Vector3> newTweener = Tweener<Vector3>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return from + (to - from) * LerpFunction.lerfs[(int)newTweener.lerptype](0, 1, time); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<Vector4> getter, MySetter<Vector4> setter, Vector4 endValue, float duration) { // 设置属性 Tweener<Vector4> newTweener = Tweener<Vector4>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return from + (to - from) * LerpFunction.lerfs[(int)newTweener.lerptype](0, 1, time); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<Quaternion> getter, MySetter<Quaternion> setter, Quaternion endValue, float duration) { // 设置属性 Tweener<Quaternion> newTweener = Tweener<Quaternion>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return Quaternion.Lerp(from, to, LerpFunction.lerfs[(int)newTweener.lerptype](0, 1, time)); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<Rect> getter, MySetter<Rect> setter, Rect endValue, float duration) { // 设置属性 Tweener<Rect> newTweener = Tweener<Rect>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return new Rect(LerpFunction.lerfs[(int)newTweener.lerptype](from.x, to.x, time), LerpFunction.lerfs[(int)newTweener.lerptype](from.y, to.y, time), LerpFunction.lerfs[(int)newTweener.lerptype](from.width, to.width, time), LerpFunction.lerfs[(int)newTweener.lerptype](from.height, to.height, time)); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<RectOffset> getter, MySetter<RectOffset> setter, RectOffset endValue, float duration) { // 设置属性 Tweener<RectOffset> newTweener = Tweener<RectOffset>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return new RectOffset((int)LerpFunction.lerfs[(int)newTweener.lerptype](from.left, to.left, time), (int)LerpFunction.lerfs[(int)newTweener.lerptype](from.right, to.right, time), (int)LerpFunction.lerfs[(int)newTweener.lerptype](from.top, to.top, time), (int)LerpFunction.lerfs[(int)newTweener.lerptype](from.bottom, to.bottom, time)); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } public static Tweener To(MyGetter<Color> getter, MySetter<Color> setter, Color endValue, float duration) { Tweener<Color> newTweener = Tweener<Color>.Create(getter, setter, endValue, duration); newTweener.change = (from, to, time) => { return Color.Lerp(from, to, LerpFunction.lerfs[(int)newTweener.lerptype](0, 1, time)); }; // 加入Tween AddCoroutineAndTween(newTweener); return newTweener; } #endregion #region 调用Manager类函数 public static void AddCoroutineAndTween(Tween tween) { MyTweenManager manager = MyTweenManager.GetInstance(); manager.AddCoroutineAndTween(tween); } public static void DeleteCoroutineAndTween(Tween tween) { MyTweenManager manager = MyTweenManager.GetInstance(); manager.DeleteCoroutineAndTween(tween); } public static List<Tween> GetAllTween() { MyTweenManager manager = MyTweenManager.GetInstance(); return manager.GetAllTween(); } public static List<Tween> GetAllPauseTween() { MyTweenManager manager = MyTweenManager.GetInstance(); return manager.GetAllPauseTween(); } public static List<Tween> GetAllPlayingTween() { MyTweenManager manager = MyTweenManager.GetInstance(); return manager.GetAllPlayingTween(); } #endregion } }
MyTweenManager:(继承MonoBehaviour,调用协程)
关于协程部分可以点我
/* * 描 述:实现DoTweenManager类,用于挂在在脚本上并调用协程 * 作 者:hza * 创建时间:2017/05/07 21:25:03 * 版 本:v 1.0 */ using My.DoTween; using My.DoTween.Core; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; // Pair数据结构 public class Pair<T1, T2> { public T1 first; public T2 second; public Pair(T1 first, T2 second) { this.first = first; this.second = second; } } public class MyTweenManager : MonoBehaviour { private static MyTweenManager _instance; public static MyTweenManager GetInstance() { if (_instance == null) { // 要使用时,创建新空物体并把脚本挂载在上面 GameObject gameobject = new GameObject("[MyToTweenManager]"); gameobject.AddComponent<MyTweenManager>(); _instance = gameobject.GetComponent<MyTweenManager>(); } return _instance; } // 储存正在进行的tween和对应的协程的Pair,Key值为Tween的id属性 private static Dictionary<object, Pair<Tween, Coroutine>> tweenDictionary = new Dictionary<object, Pair<Tween, Coroutine>>(); // 加入新Tween,并创建线程 public void AddCoroutineAndTween(Tween tween) { if (tweenDictionary.ContainsKey(tween.id) || tween.id == null) throw new InvalidCastException("该动作已经在进行"); // 如果设置自动播放,则立刻播放 tween.pause = !MyDoTween.StartAuto; // 加入Tween tweenDictionary.Add(tween.id, new Pair<Tween, Coroutine>(tween, StartCoroutine(ExcitingProgramming.Todo(this, tween)))); } //删除Tween,并停止线程 public void DeleteCoroutineAndTween(Tween tween) { if (!tweenDictionary.ContainsKey(tween.id)) throw new KeyNotFoundException("不存在该动作!"); // 停止线程 StopCoroutine(tweenDictionary[tween.id].second); // 删除该tween tweenDictionary.Remove(tween.id); } // 寻找字典中所有的Tween public List<Tween> GetAllTween() { List<Tween> tweenList = new List<Tween>(); foreach (KeyValuePair<object, Pair<Tween, Coroutine>> pair in tweenDictionary) tweenList.Add(pair.Value.first); return tweenList; } // 寻找字典中暂停的Tween public List<Tween> GetAllPauseTween() { List<Tween> tweenList = new List<Tween>(); foreach (KeyValuePair<object, Pair<Tween, Coroutine>> pair in tweenDictionary) if (!pair.Value.first.stop && pair.Value.first.pause) tweenList.Add(pair.Value.first); return tweenList; } // 寻找字典中正在播放的Tween public List<Tween> GetAllPlayingTween() { List<Tween> tweenList = new List<Tween>(); foreach (KeyValuePair<object, Pair<Tween, Coroutine>> pair in tweenDictionary) if (!pair.Value.first.stop && !pair.Value.first.pause) tweenList.Add(pair.Value.first); return tweenList; } } // 协程的参数函数 public static class ExcitingProgramming { public static IEnumerator Todo(MyTweenManager manager, Tween tween) { // 从下一帧开始 yield return null; // 判断是否stop while (!tween.stop) { if (tween.pause) { yield return null; continue; } tween.Update(Time.deltaTime); yield return null; } // 清除tween manager.DeleteCoroutineAndTween(tween); // 删除tween if (tween is Tweener) MyDoTween.FreeTweener(tween); else MyDoTween.FreeSequence(tween); } }
test3:(测试代码)
using System.Collections; using System.Collections.Generic; using UnityEngine; using My.DoTween; using My.DoTween.Core; public class test3 : MonoBehaviour { // Use this for initialization void Start () { Tween tween = transform.DORotate(new Vector3(0, 0, 360), 2.5f).SetLoopTime(-1); transform.DOMoveY(10, 5).SetEaseType(My.LerpFunctionSpace.LerpFunctionType.SineBoth); Sequence se2 = MyDoTween.Sequence(); se2.Append(transform.DOMoveX(5, 2.5f).SetEaseType(My.LerpFunctionSpace.LerpFunctionType.SineOut)) .Append(transform.DOMoveX(0, 2.5f).SetEaseType(My.LerpFunctionSpace.LerpFunctionType.SineIn)) .AppendInterval(1f) .AppendCallback((t, u) => { tween.Stop(); transform.DOScale(3, 1); transform.DOMoveY(0, 1.5f).SetEaseType(My.LerpFunctionSpace.LerpFunctionType.BounceOut); }); } // Update is called once per frame void Update () { } }
测试了一下,结果如下(还是可以实现各种动作的):
总结:
感觉类的关系还是有些搞不清啊,写的特慢,改来改去。什么时候能改掉这个大毛病呢= =相关文章推荐
- 一步一步使用Unity3d工具实现AR开发入门
- MyBatis从入门到放弃一:从SqlSession实现增删改查
- 【Unity3D】 DoTween实现飘字的效果
- Unity3D 从入门到放弃(四)----打飞碟
- vuex - modal的实现 =>从入门到放弃(三)
- vuex - modal的实现 =>从入门到放弃(一)
- unity3d 入门——实现井字棋
- Unity3D 从入门到放弃 ——巡逻兵 观察者模式
- JavaWeb从入门到放弃(9)-实现一个客户端上传文件到服务端
- JavaScript从入门到放弃(3)-对象的不同创建方法-实现真正的面向对象
- 拒绝从入门到放弃_《Openstack 设计与实现》必读目录
- Unity3D 从入门到放弃(五)----射箭游戏
- Unity3D 从入门到放弃(六)-----巡逻兵
- Python爬虫从入门到放弃(二十三)之 Scrapy的中间件Downloader Middleware实现User-Agent随机切换
- 放弃class与js实现隔行换色效果
- arm wince EVC入门之一: 实现远程调试的最佳硬件途径
- Visual C# 入门 -Office 编程(如何实现 - C#)
- EVC入门之一: 实现远程调试的最佳硬件途径
- 入门6-Silverlight 1.0中多媒体影音的实现
- PHP入门手记-简单实现网页密码验正