【Unity】DOTween
介绍
Tweener
和Sequence
是Tween
的子类Tweener
是播放的单个动画Sequence
控制Tweener
的播放
容易踩坑点
一个
Tweener
的循环为3时,那么他们三个算一个完整的动画当
Tweener
添加到Sequence
之后Tweener
的大部分属性设置会被覆盖,比如循环,Pause()
最容易照成的误区,动画为从原点向前移动5,
Restart()
之后将重复刚才的动画,也就是说他会先回到原点再向前移动5如果为设置
SetAutoKill(false)
会在动画播放完一次之后就销毁掉,并且使用_sequence.Restart()
并不会有反应,如果动画不是第一次播放,并且没有效果的话,可以检查一下定义这个动画的时候有没有使用SetAutoKill(false)
。但是在使用SetAutoKill(false)
之后,记得在合适的时候使用_sequence = null
销毁掉对象,避免内存泄漏
Tweener
控制播放周期
可以将其想象成视频的播放按钮,打开一个视频的时候他会开始自动播放,除非暂停。
暂停之后,需要点击Play继续播放
视频放完之后再次点击Play没用,只能Restart。
Tweener
方法如下
Play()
:继续播放动画,在实例化Tweener
的时候就会Pause()
:暂停动画,使用Play()
继续播放PlayForward()
:动画向前播放PlayBackwards()
:动画向后播放Restart(bool, float)
:重新开始播放动画;是否忽略SequenceKill(bool)
:结束动画;如果为true就瞬间完成动画,false停在当前位置
回调函数
动画周期内触发的回调:
OnStart
:只有在第一次播放时才会回调OnPlay
:在动画开始播放时回调:第一次播放、Play()
、暂停后的Play()
、Restart()
OnUpdate
:动画播放的期间回调,最好不要嵌套再嵌套OnStepComplete
:在每次完成一个循环时都会触发,以为着,如果loops为3将被调用3次,而OnComplete
只在最后被回调一次OnComplete
:在整个动画完成时调用,包括循环OnPause
:在动画停止播放时回调,播放完整个动画、Pause()
、Kill(true)
需用户手动触发的回调:
OnKill
:触发kill()
时回调OnRewind
:触发Restart()
时回调OnWayPoineChange
:唯一一个有参数的回调,主要用于DoPath
函数,当走到一个点位时回调
使用技巧
改变数值
如果需要改变的是普通的数值,而不是Transform,可以使用一下方法
1 | private DOGetter<float> _radiusGetter; // 其实就是一个获取数值的委托 |
Sequence使用示例
1 | private Sequence bounceSequence; |
倒放动画
1 | private Tweener amplifyTween; |
终止动画
当前dotween动画没播放完,便再次播放有冲突的操作,如连续多次播放、正播、倒播,导致显示不正常或报错。
解决方法:在每次开始执行播放动画时,先加上下面对应类似的杀死进程代码,就OK了
1 | transform.DOKill(); |
忽略timeScale影响
让DOTweenAnimation忽略Time.timeScale = 0
的影响
1 | tween.SetUpdate(true); |
360度旋转
设置Rotate
旋转模式
1 | transform.DOLocalRotate(new Vector3(0, 0, -360), 2, RotateMode.FastBeyond360) |
Form()
DOTween的参数默认都是目标值,使用From后参数代表起点
1 | // 绝对位置,若当前坐标(1,0,0),即从5运动到1 |
SetLoops(int loops, LoopType loopType)
loops
:循环次数,-1为无数次循环loopType
:循环模式Restart
:从头开始循环(默认)Yoyo
:交替来回移动Incremental
:设置为相对运动后才生效,连续“向前”移动(A到B, B到B+(A-B), …)
SetRelative()
设置为相对运动
SetEase
这里可以参考 👉 | https://easings.net | 👈 上的曲线效果
Flash
示例
UniTask配合
想要将DoTween转换成UniTask,需要在ProjectSetting - Player - OtherSetting - ScriptingDefineSymbols中添加UNITASK_DOTWEEN_SUPPORT
优点:
可以使用await,而不是OnComplete回调函数,使代码更直观
1
2
3
4
5
6private async void Start()
{
await transform.DOMove(new Vector3(5f, 0, 5f), 2); // 先移动
await transform.DORotate(new Vector3(90f, 90, 90f), 2); // 再旋转
Debug.Log("Complete"); // 最后再输出
}可以使用WithCancellation方法取消DOTween
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public class UniTaskWithDOTween : MonoBehaviour
{
private CancellationTokenSource _cts = new CancellationTokenSource();
private async void Start()
{
await transform.DOMove(new Vector3(5f, 0, 5f), 2).WithCancellation(_cts.Token);
Debug.Log("Complete");
}
private void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
{
_cts.Cancel();
}
}
private void OnDestroy()
{
_cts?.Dispose();
}
}
注意:
如果想要重复使用tweenrs(
SetAutoKill(false)
),则永远不会触发await下方的代码如果想要等待另一个时间点,可以使用扩展方法
AwaitForComplete
,AwaitForPause
,AwaitForPlay
,AwaitForRewind
,AwaitForStepComplete
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 public class UniTaskWithDOTween : MonoBehaviour
{
private Tweener tween;
private void Awake()
{
tween = transform.DOMove(new Vector3(5f, 0, 5f), 2).Pause();
}
private async void Start()
{
await tween.AwaitForPlay(); // 先是被挂起,当在Update中检测到鼠标右键点击后,再执行下方代码
Debug.Log("Play");
}
private void Update()
{
if (Mouse.current.rightButton.wasPressedThisFrame)
{
tween.Play();
}
}
}
参考