Dotween的大多数Tween函数以拓展方法的形式提供。
Basic Settings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 使用TweenParams
TweenParams para = new TweenParams();
para.SetLoops(-1, LoopType.Yoyo);
transform.DOMove(Vector3.one, 2).SetAs(para);
transform.DOMove(position, duration) // 动画:目标值/偏移值 + 时长/速度
// 基本配置
.SetSpeedBased() // 动画基于速度而不是时长
.From() // 目标位置设为初始位置
.SetRelative() // 增量运动, true=偏移量, falese=目标值
.SetDelay(1) // 设置延时
.SetId("Id") // 设置动画ID
.SetLoops(-1, LoopType.Yoyo) // 设置循环次数和类型(重新开始,Yoyo,累加)
.SetUpdate(UpdateType.Normal, true) // 设置动画的帧函数, 第二个参数 TRUE = ignoreTimeScale
.SetRecyclable(true) // 设置是否可回收
// 为true的话,动画播放完会被回收,缓存下来,不然播完就直接销毁
.SetAutoKill(false) // 非无限循环的动画是否自动destroy;
// 若非无限循环的动画为false,停止后可以Restart(),否则不可以
.Pause() // 创建时处于暂停状态
// Ease曲线
.SetEase(Ease.Linear) // 默认Ease曲线
.SetEase(AnimationCurve) // 使用AnimationCurve当作参数
.SetEase(MyEaseFun) // 自定义, 以回调函数为参数
// 回调函数
.OnComplete(() => { }) // 动画完成回调
.OnStepComplete( () => {}) // 完成单个循环周期时触发
.OnKill(() => { }) // 动画销毁时回调
.OnStart(() => { }) // 只在第一次播放动画时调用,在play之前调用
.OnPlay(() => { }) // 动画播放时回调,暂停后重新播放也会调用
.OnPause(() => { }) // 动画暂停时回调
.OnRewind(() => { }) // 动画回退时回调, 以下情况会被调用
// 使用DORestart重新播放时
// 使用Rewind倒播动画完成时
// 使用DOFlip翻转动画完成时
// 使用DOPlayBackwards反向播放动画完成时
.OnUpdate(() => { }) // 帧回调
.OnWaypointChange((value) => { }) // 在路径动画时,改变目标点时的回调,参数为当前目标点的下标
);
//返回值是运动距离的百分比 值应为0~1之间,最后的值需为1,不然停留的位置不会是目标位置
private float MyEaseFun(float time, float duration, float overshootOrAmplitude, float period)
{
return time / duration;
}
//
// Demo
using DG.Tweening; //引入命名空间
public class DOTWeenTest : MonoBehaviour
{
Tweener twe; //声明一个Tweener对象
void Start()
{
twe = transform.DOMove(new Vector3(3, 4, 0), 2);//将动画保存在Tweener对象中
twe.Pause();//暂停,防止自动播放
twe.SetAutoKill(false);//关闭动画自动销毁
}
//创建两个方法事件,控制前放后倒放
public void Forward()
{
twe.PlayForward(); //该动画正放
}
public void Back()
{
twe.PlayBackwards(); //该动画倒放
}
}
Controlling
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 一共有三种方式控制tween动画, 所有三种方式共享相同的方法名,只是扩展方法形式增加了 DO 前缀
// 1. 通过DOTween类的静态函数控制
DOTween.PauseAll(); // All version
DOTween.Pause("badoom"); // Id version
DOTween.Pause(transform); // target version
// 2. 直接通过tween动画控制
myTween.Pause();
// 3. 扩展方法形式
transform.DOPause();
// 如果想在动画结束之后使用这些方法,一定要disable掉 AutoKill
transform.DOPlay(); // 播放,播放的动画不能是正在播放的,也不能是播放完成的
transform.DOPause(); // 暂停此组件上的所有动画
transform.DORestart(); // 重播
transform.DORewind(); // 倒播,此方法会直接退回起始点
transform.DOSmoothRewind(); // 平滑倒播,此方法会按照之前的运动方式从当前位置退回起始点
transform.DOKill(); // 销魂此组件上的所有动画
transform.DOFlip(); // 翻转补间的方向
transform.DOGoto(1.5f, true); // 跳转, (跳转的时间点,跳转后是否播放动画)
transform.DOPlayBackwards(); // 反向播放动画
// 在动画播放到一半时执行,会退回起始点,在一开始执行看不到效果是因为,物体本身就在起始点
transform.DOPlayForward(); // 正向播放动画
transfomr.TogglePause(); // 当暂停时,执行就继续播放,播放时,执行就暂停
Get Tween Data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// DOTween类的静态方法
DOTween.PausedTweens(); // 返回所有暂停的动画,没有则返回null
DOTween.PlayingTweens(); // 返回所有真正播放的动画,没有则返回null
DOTween.TweensById("id", true); // 返回对应ID的动画数组,第二个参数表示是否只收集正在播放的动画
DOTween.TweensByTarget(transform, true); // 返回给定对象的数组
DOTween.IsTweening(transform); // 收集传入的对象是否有动画在活动
DOTween.TotalPlayingTweens(); // 正在播放的动画的总数,目前处于延迟播放状态的动画也算
// 动画实例的方法
tweener = transform.DOMove(Vector3.one, 2);
tweener.fullPosition = 1; // 表示动画执行位置的属性,可读可写
tweener.CompletedLoops(); // 表示动画执行完的次数
tweener.Delay(); // 获取动画的延迟时间
tweener.Duration(false); // 获取动画的持续时间, 参数为true 表示计算循环的时间,无限循环为Infinity
tweener.Elapsed(); // 动画已播放的时间, 参数为true 表示计算循环的时间
tweener.ElapsedDirectionalPercentage(); // 返回动画进度的百分比, [0~1]
tweener.ElapsedPercentage(true); // 返回动画区间已用的百分比, true=返回值是循环总区间的已用百分比
tweener.IsActive(); // 动画是否在活动
tweener.IsBackwards(); // 是否是反向动画
tweener.IsComplete(); // 动画是否完成
tweener.IsInitialized(); // 是否已经初始化
tweener.IsPlaying(); // 是否正在播放
tweener.Loops(); // 返回循环次数,无限循环为Infinity
WaitFor Coroutines / Tasks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private IEnumerator PlayAnimation()
{
tweener = transform.DOMove(Vector3.one, 2);
yield return tweener.WaitForCompletion(); // 等待动画执行完
yield return tweener.WaitForElapsedLoops(2); // 等待指定的循环次数
yield return tweener.WaitForKill(); // 等待动画被杀死
yield return tweener.WaitForPosition(0.5f); // 等待动画执行指定时间
// 等待动画回退, 以下情况会继续执行函数
// 使用DORestart重新播放时
// 使用Rewind倒播动画完成时
// 使用DOFlip翻转动画完成时
// 使用DOPlayBackwards反向播放动画完成时
yield return tweener.WaitForRewind();
yield return tweener.WaitForStart(); // 等待Start执行后继续执行
}
private async Task PlayAnimation()
{
myTween = transform.DOMove(Vector3.one, 2);
await myTween.AsyncWaitForCompletion();
await myTween.AsyncWaitForElapsedLoops();
await myTween.AsyncWaitForKill();
await myTween.AsyncWaitForPosition(0.3f);
await myTween.AsyncWaitForRewind();
await myTween.AsyncWaitForStart();
}
Tweener - Any Value
1
2
int timer = 0;
DOTween.To( () => timer, x => timer = x, 0.2f, animDuration);
Tweener - Transform
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
transform.DOMove(); // 世界坐标移动
transform.DOLocalMove(); // 局部坐标移动
transform.DORotate(new Vector3(0, 90, 0), 2); // 旋转到给定的值,改变的是欧拉角
transform.DORotateQuaternion(new Quaternion(0.1f, 0.1f, 0.1f, 0.1f), 2); // 旋转到给定的值,改变四元数
transform.DOLocalRotate(new Vector3(0, 90, 0), 2);
transform.DOLocalRotateQuaternion(new Quaternion(0.1f, 0.1f, 0.1f, 0.1f), 2);
transform.DOLookAt(new Vector3(0, 0, 0), 2); // 平滑的让自身的z轴正方向指向目标点
transform.DOScale(new Vector3(2, 2, 2), 2);
transform.DOScaleX(3, 2);
// 冲击
transform.DOPunchPosition(new Vector3(0, 1, 0), duration, vibrato, elascity);
transform.DOPunchRotation(new Vector3(0, 90, 0), 2, 2, 0.1f);
transform.DOPunchScale(new Vector3(2, 2, 2), 2, 2, 0.1f);
// 震动
transform.DOShakePosition(1, 5, 10, 50, true);
transform.DOShakeRotation(3);
transform.DOShakeScale(3);
// 混合动画
// 原本同时执行两个Move方法,只会执行最新的一个动画命令
// 假设起始点为(0,0,0),结果是物体运动到了(2,2,2)
transform.DOMove(new Vector3(1, 1, 1), 2);
transform.DOMove(new Vector3(2, 2, 2), 2);
// DOBlendableMoveBy允许多个同时执行, 且它是增量动画,参数不是目标点,而是要移动的量
// 假设起始点为(1,1,1),最后动画停止时的坐标是(1,2,2)
transform.DOBlendableMoveBy(new Vector3(1, 1, 1), 1);
transform.DOBlendableMoveBy(new Vector3(-1, 0, 0), 1);
Tweener - uGUI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// RectTransform
trans.DOAnchorPos()
// Image
image.DOFade(endValue, duration).SetAutoKill(false).Pause(); // 渐变
image.DOColor(endValue, duration).SetEase(Ease.Linear).Pause(); // 颜色
image.DOFillAmount(endValue, duration).SetEase(Ease.Linear).SetLoops(-1, LoopType.Yoyo) //填充
.OnStepComplete( () => {
image.fillClockwise = !image.fillClockwise;
}).Pause();
// Text 通过动画把现有text变成value值。(Replace, Add, Scramble)
text.DOText("This text will replace the existing one", duration).Pause(); // 替换
text.DOText("This text will be added to the existing one", duration).Pause(); // 追加
text.DOText("This text will appear from scrambled chars", duration, true, ScrambleMode.All); // 乱码
// Slider
slider.DOValue(1, duration); // 滑动条的值
Tweener - Materials
1
2
3
4
5
6
7
8
9
Material material;
material.DOColor(toColor, duration); // 材质颜色
material.DOColor(Color.clear, "_Color", 2); // 按照shader的属性名,修改颜色
material.DOColor(toColor, "_EmissionColor", duration); // 发光
material.DOFade(0, 2); // 修改alpha值
material.DOGradientColor(Gradient, "_Color", 3); // 颜色渐变
material.DOOffset(new Vector2(1, 1), 2); // 改变材质offset的值
material.DOVector(new Vector4(0, 0, 0, 1), "_Color", 3); // 改变shader属性的名称对应的Vector4值
material.DOBlendableColor(Color.red, "_Color", 3); // 颜色混合
Tweener - Camera
1
2
3
4
5
6
7
8
9
camera.DOAspect(0.6f, 2); // 屏幕视角的宽高比
camera.DOColor(Color.blue, 2); // 改变相机background参数的颜色
camera.DONearClipPlane(200, 2); // 改变相机近切面的值
camera.DOFarClipPlane(2000, 2); // 改变相机远切面的值
camera.DOFieldOfView(30, 2); // 改变相机FOV的值
camera.DOOrthoSize(endValue, duration); // 改变相机正交大小
camera.DOPixelRect(new Rect(0f, 0f, 600f, 500f), 2); // 按照屏幕像素计算的显示范围
camera.DORect(new Rect(0.5f, 0.5f, 0.5f, 0.5f), 2); // 按照屏幕百分比计算的显示范围
camera.DOShakePosition(1, 10, 10, 50, false); // 相机震动
Sequence
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DOTween.Sequence() // 返回一个新的Sequence
.Append(nestedTween) // 添加动画到队列中
.AppendInterval(1) // 添加时间间隔
.Insert(2, nestedTween) // 按时间点插入动画, 第一个参数为时间
.Join(nestedTween) // 加入的动画和当前正在执行的动画一起执行
.PrependCallback( () => {} ) // 前置回调, 在Sequence的最开始添加回调
.InsertCallback(3.0f, InsertCallBack) // 按时间点插入回调函数
.AppendCallback(CallBack); // 添加回调到动画中
Sequence s = DOTween.Sequence();
// 添加动画到队列中
s.Append(cube.DOMoveX(6, duration).SetRelative().SetEase(Ease.InOutQuad));
// 按时间点插入动画
s.Insert(0, cube.DORotate(new Vector3(0, 45, 0), duration / 2).SetEase(Ease.InQuad).SetLoops(2, LoopType.Yoyo));
s.Insert(duration / 2, cube.GetComponent<Renderer>().material.DOColor(Color.yellow, duration / 2));
// Set the whole Sequence to loop infinitely forward and backwards
s.SetLoops(-1, LoopType.Yoyo);
Paths
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public Transform target;
public PathType pathType = PathType.CatmullRom;
public Vector3[] waypoints = new[] {
new Vector3(4, 2, 6),
new Vector3(8, 6, 14),
new Vector3(4, 6, 14),
new Vector3(0, 6, 6),
new Vector3(-3, 0, 0)
};
void Start()
{
// Create a path tween using the given pathType, Linear or CatmullRom (curved).
// Use SetOptions to close the path
// and SetLookAt to make the target orient to the path itself
Tween t = target.DOPath(waypoints, 4, pathType)
.SetOptions(true)
.SetLookAt(0.001f);
// Then set the ease to Linear and use infinite loops
t.SetEase(Ease.Linear).SetLoops(-1);
}
// DoTween Path Component
Follow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public Transform target; // Target to follow
Vector3 targetLastPos;
Tweener tween;
void Start()
{
// First create the "move to target" tween and store it as a Tweener.
// In this case I'm also setting autoKill to FALSE so the tween can go on forever
// (otherwise it will stop executing if it reaches the target)
tween = transform.DOMove(target.position, 2).SetAutoKill(false);
// Store the target's last position, so it can be used to know if it changes
// (to prevent changing the tween if nothing actually changes)
targetLastPos = target.position;
}
void Update()
{
// Use an Update routine to change the tween's endValue each frame
// so that it updates to the target's position if that changed
if (targetLastPos == target.position) return;
// Add a Restart in the end, so that if the tween was completed it will play again
tween.ChangeEndValue(target.position, true).Restart();
targetLastPos = target.position;
}
Dotween Animation Component
制作与设计
- 不想直接播放,就不要选中 AutoPlay
- 如果非无限循环的动画如果以后想要重复播放,就不要选中 AutoKil
代码控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 根据ID控制动画 // 播放 DOTween.Restart("id"); // 停止 DOTween.Complete("id"); // 控制单个 DOTweenAnimation 组件 [SerializeField] private DOTweenAnimation bg; bg.DORestart(); bg.DOPlayNext(); // 播放下一个Tween Animation bg.DOPlayById(id); // 播放指定ID的动画 bg.DOPlayAllById(id); bg.DORestartById(); bg.DORestartAllByID();
常见问题
想要复用动画,不能调用Play(),需要调用Restart()方法
调用play方法,这个动画 不能是正在播放的,也不能是播放完成的,
Restart方法成功调用必须保证 AutoKill = false
原本同时执行两个Move方法,只会执行最新的一个动画命令
DOBlendableMoveBy允许多个同时执行, 且它是增量动画,参数不是目标点,而是要移动的量