您的位置:首页 > 移动开发 > Unity3D

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