DOTween是最常用的动画插件之一,比使用Unity自带脚本写动画,方便很多。
插件获取
untiy商店插件地址
https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676
DOTween商城地址,开发文档
导入和设置
DOTween首次使用需要设置,导入以后会弹出下面的窗口,点击按钮就好。
之后点击绿色的“Setup DOTween”按钮就能设置。下面的那个青色的按钮是生成一个ASMDEF文件,让写脚本的时候不必每次都去编码DOTween的内容,提高写完代码切换的速度。
这个窗口可以通过菜单Tools/Demigiant/DOTween Utility Panel再次打开,要访问官网查看文档通过这里都很方便。
点击了按钮就显示这个界面,默认全选就好,再选中Apply按钮就可以了。
使用
使用前需要添加引用命名空间
using DG.Tweening;
基本写法有两种
一、通用方法
DOTween.开头的官方叫通用方法,其中最常用的就是DOTween.To(getter, setter, to, float duration)。绝大多数动画都可以用这个方法解决。前2个输入的是代理。无论是控制移动,旋转,颜色变化,文字变化都可以用这个方法。getter是初始值
,setter是变化的值
,to是目标,duration是变化时长。
DOTween.To(()=> myVector, x=> myVector = x, new Vector3(3,4,8), 1); DOTween.To(()=> 0, x=> myFloat = x, 50, 5); DOTween.To(() => 0, AddChar, message.Length, message.Length * duration);
二、便捷方法
便捷方法是 Unity的各种属性.DOXXX,简单说就是能少打几个字。例如让当前游戏对象移动到某个位置的DOMove。
transform.DOMove(Vector3.right * 3, 2);
不同属性后面可以DO出不同的动作,而且参数不同。一般常见的动画变化都有,推荐看一下官方文档有个大概印象,使用的时候,遇到对应属性的动画的时候,DO出来再靠代码提示来选择就好。
添加设置
主要的语句完了以后,可以通过点,点出更多的设置跟在后面,如常见的循环。
transform.DOMove(Vector3.right * 8, 2).SetLoops(3, LoopType.Yoyo);
事件响应
对于动画的事件响应也是点出来跟在后面的。
transform.DOMove(Vector3.right * 8, 2).OnComplete(OnEnd); transform.DOMove(Vector3.right * 8, 2).OnComplete(() => Debug.Log("Text Complete!"));
DoTween的一些常用用法
立即完成动画
这在某些情况下非常有用,例如当你想在某个条件满足时立即停止动画,或者在程序中的特定时间点将动画重置为起始状态。
特别是频繁调用动画时,我们在上一个动画还没有完成的情况下,紧接着就进行下一个动画,会造成了物体大小畸形
的问题
//用于立即完成正在进行的 Tweener 或 Sequence 动画 transform.DOComplete();
立即停止所有正在播放的动画
这个方法在某些情况下可能很有用,例如:
- 当你需要在游戏中重新加载或重置某些场景时,你可能希望清除所有正在播放的动画,以确保它们不会在重置后继续影响游戏逻辑。
- 当你想要在游戏中暂停或切换到另一个状态时,你可以使用
DOTween.Clear()
来停止当前所有的动画,以确保在状态转换时不会出现不良的过渡效果。
//清除 DOTween 库中当前正在进行的所有动画和补间 DOTween.Clear()
移动动画
//使得物体移动,第一个参数类型是Vector3,代表物体要移动到的世界坐标,第二个参数是移动到该位置所需要的时间 transform.DOMove(new Vector3(5, 9, 1), 6); //使得物体在x轴进行移动,第一个参数是移动到的x的位置,以自身坐标 transform.DOLocalMoveX(9, 7); //blend会对物体的运动进行一个累加第一个参数,需要累加的数,第二个参数是所需要的时间 transform.DOBlendableMoveBy(Vector3.one, 2); //使得物体到达参数一的位置就进行往返运动, //第一个参数是所能到达的位置 //第二个参数是所需要的时间 //第三个参数是往返的次数 //第四个参数是值越大,反方向给的力就越大 transform.DOPunchPosition(new Vector3(0, 5, 0), 5, 2, 0.5f);
旋转
模式
RotateMode.Fast //旋转不超过360度 RotateMode.FastBeyond360//旋转超过360度 RotateMode.WorldAxisAdd//旋转将按照世界坐标系的轴进行旋转 RotateMode.LocalAxisAdd//按局部坐标轴进行增量旋转
例子
//使得物体进行旋转,第一个参数是要到达的最终值,第二个是渐变的持续时间 transform.DORotate(new Vector3(5, 9, 1), 4); //参数1:旋转到的角度 参数2:动画的时间 参数3:旋转的模式 transform.DORotate(new Vector3(0, 360, 0), 10f, RotateMode.WorldAxisAdd); //使物体一直旋转 transform.DORotate(new Vector3(0, 180, 0), 1f, RotateMode.Fast).SetLoops(-1, LoopType.Restart); //使得物体进行旋转,以自身为坐标轴,第一个参数是要到达的最终值,第二个是渐变的持续时间 transform.DOLocalRotate(new Vector3(4, 8, 9), 4); //使得物体进行旋转,以世界坐标系,第一个参数是四元数,第二个是所需要的时间的值 transform.DORotateQuaternion(Quaternion.Euler(40, 8, 5), 7);
让游戏对象以线性速度不断地绕着Z轴逆时针旋转360度,并且循环播放该旋转动画
transform.DORotate(new Vector3(0, 0, -360), 2f, RotateMode.FastBeyond360).SetEase(Ease.Linear).SetLoops(-1, LoopType.Restart);
transform.DORotate(new Vector3(0, 0, -360), 2f, RotateMode.FastBeyond360)
:这部分代码使用DOTween库的DORotate
方法来实现旋转动画。DORotate
方法接受三个参数:旋转的目标角度(这里是new Vector3(0, 0, -360)
表示绕着Z轴逆时针旋转360度),持续时间(2秒),以及旋转模式(RotateMode.FastBeyond360
表示快速旋转超过360度)。这意味着对象将会以较快的速度旋转超过360度,而不是简单地从起始角度旋转到目标角度。.SetEase(Ease.Linear)
:这部分代码使用了.SetEase
方法来设置缓动类型。在这里,缓动类型被设置为Ease.Linear
,表示旋转动画将以线性速度进行,即匀速运动。.SetLoops(-1, LoopType.Restart)
:最后,使用.SetLoops
方法设置动画的循环次数和循环类型。第一个参数-1
表示无限循环播放,第二个参数LoopType.Restart
表示每次循环都从头开始播放动画。
尺寸,缩放
//使得物体进行扩大,第一个参数是扩大的值,第二个值是所需要的时间 transform.DOScale(new Vector3(3, 4, 5), 8); //使物体从0扩大到1, tf.DOScale(Vector3.one, 0.5f).From(Vector3.zero);
弹跳
# 参数解释 # endValue:到达的结束值 # jumpPower:跳跃的功率(跳跃的最大高度由this加上最后的Y偏移量) # numJumps:总跳跃次数 # duration:渐变的持续时间 # snapping :如果为TRUE,渐变将平滑地将所有值捕捉为整数 transform.DOJump(Vector3 endValue, float jumpPower, int numJumps, float duration, bool snapping = false) // 5秒内弹跳3次,弹到10,10,10位置 transform.DOJump(new Vector3(10, 10, 10), 3, 5f).SetEase(Ease.OutBack);
渐变透明度
// text 2秒内渐变透明到0 text.DOFade(0, 2f).SetEase(Ease.OutSine);
震动
# 参数1:指定抖动效果的持续时间,以秒为单位。 # 参数2:定义抖动的强度。可以是一个Vector3类型的值,分别表示X、Y和Z轴上的抖动强度。 # 参数3:指定抖动的次数。例如,10表示在持续时间内进行10次振动。 # 参数4:添加一些随机因素以使抖动看起来更自然。值为0表示没有随机性,值为1表示完全随机。 # 参数5:抖动效果是否被限制在整数值,这个参数用于定义抖动是否应该以整数值进行位置、旋转或缩放。 //使物体的位置发生抖动 transform.DOShakePosition(1, new Vector3(0, 0.5f, 0), 20, 0.5f, false); //使物体的旋转发生抖动 transform.DOShakeRotation(0.3f, new Vector3(10f, 10f, 10f), 4, 0, true); //使物体的缩放发生抖动 transform.DOShakeScale(0.5f, 0.2f, 10, 0.5f, true);
材质
Material material = GetComponent<MeshRenderer>().material; //改变材质的颜色 material.DOColor(Color.red, 5); //实现渐变,第一个参数是渐变条,需要提前声明public Gradient gradient;,第二个参数是时间 material.DOGradientColor(gradient, 5); //改变贴图位置 material.DOOffset(Vector3.one,0); //将两个材质的颜色混合在一起 material.DOBlendableColor(Color.red, 5); material.DOBlendableColor(Color.yellow, 5);
摄像机
//改变摄像机的宽高比,第一个参数是宽高之比,第二个参数是所达成所需要的时间 camera.DOAspect(0.5f, 5); //改变摄像机的背景颜色 camera.DOColor(Color.black, 5); //改变摄像机拍摄内容的角度,第一个参数是角度大小,第二个参数是时间 camera.DOFieldOfView(2, 5); //改变正交摄像机拍摄内容的角度,第一个参数是角度大小,第二个参数是时间 camera.DOOrthoSize(10, 7); //实现分屏的两种方式参数一 //第一个参数都是缩小之后的位置,第二个参数是按比例缩小 camera.DOPixelRect(new Rect(360, 540, 360, 540), 2); camera.DORect(new Rect(360, 360, 360, 360), 0.5f); //摄像机晃动,第一个参数是晃动的时间,第二个参数是晃动的力,第三个参数是晃动的方向 camera.DOShakePosition(2, 10, 20);
Text文字动画
旧文本控件 Text text = GetComponent<Text>(); //逐字输出,第一个参数是输出的文本,第二个参数是输出的时间,.SetEase(Ease.Linear)代表匀速输出 text.DOText("46545645646464654", 5).SetEase(Ease.Linear); 新文本控件 Text Mesh Pro并不支持DoTween的DOText方法,你也可以使用DOTween.To方法来实现TextMeshPro文本的逐字打印效果 public TextMeshProUGUI text; public string message; public float duration = 0.1f; void Start() { text.text = ""; string message = "46545645646464654" DOTween.To(() => 0, AddChar, message.Length, message.Length * duration).SetEase(Ease.Linear); } void AddChar(int index) { text.text = message.Substring(0, index); }
队列
//构建一个队列 Sequence quence = DOTween.Sequence(); //添加事件在队列之中 quence.Append(transform.DOMove(Vector3.one, 2)); //加入执行该事件,和之前一个事件一起执行 quence.Join(transform.DOScale(new Vector3(3, 4, 5), 5)); //让队列暂停1s quence.AppendInterval(1); //运行完上个事件就执行该方法 quence.AppendCallback(InsertCallBack03); quence.Append(transform.DOMove(new Vector3(1, 0, 0), 2)); //插入事件,该插入的事件是占用了插入的事件的事件,也可以在超出的事件上插入事件 //第一个参数是插入的事件,第二个参数是插入的事件 quence.Insert(0, transform.DOMove(-Vector3.one, 1)); //相当于栈反向的执行顺序,会优先执行这部分的事件 quence.PrependInterval(2); quence.Prepend(transform.DORotate(new Vector3(5, 9, 1), 4)); //最开始的时候调用该函数 quence.PrependCallback(InsertCallBack01); //在指定的事件调用该函数,第一个参数是调用的时间,第二个参数是调用的方法名字 quence.InsertCallback(6, InsertCallBack01);
设置参数
.SetLoops表示循环该事件, //里面的第一个参数代表循环的次数,当为-1的时候代表无线循环, //第二个参数为LoopType.Incremental代表累加的一个循环,每次循环完不回到之前的位置 transform.DOMove(new Vector3(2, 5, 3), 5).SetLoops(10,LoopType.Incremental); //使得动画在运行结束后停下来 transform.DOMove(new Vector3(2, 5, 3), 5).SetLoops(3,LoopType.Incremental).SetAutoKill(true); //使得动画反向进行运动,而且从目标点运动回来 transform.DOMove(new Vector3(2, 5, 3), 5).SetLoops(3,LoopType.Incremental).From(); //动画播放完成之后暂停多少时间 transform.DOMove(new Vector3(2, 5, 3), 5).SetLoops(3,LoopType.Incremental).SetDelay(1); //当使用了该参数的时候,事件的第二个参数就变成了运动到目标点的速度 transform.DOMove(new Vector3(2, 5, 3), 5).SetSpeedBased(true); //.SetId()代表给该事件一个标记,DOTween.Play(),代表去dotween的缓冲池去调用,这样做可以优化性能 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).SetId(0); DOTween.Play(0); //当.SetRelative(true)时,这个事件的第一个参数的目标地点位置就变为了一个运动的方向和长度,可以进行一个累加 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).SetRelative(true); //这个设置参数代表该事件不会受到unity事件的影响 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).SetUpdate(UpdateType.Normal,true);
运动曲线,缓动函数
基本使用
//设置曲线的运动函数 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).SetEase(Ease.); //当旋转运动曲线为flash的时候再加参数代表他来回闪烁,如果第三个参数大于0该物体的活动范围会渐渐变小,如果等于0会不变,小于0会给目标点一个力 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).SetEase(Ease.Flash,3);
Ease.Linear:线性缓动,匀速运动。
Ease.InQuad、Ease.OutQuad、Ease.InOutQuad:二次缓动,可以实现平滑加速、平滑减速、先加速后减速的效果。
Ease.InOutSine:正弦缓动,产生类似物体来回摆动的效果。
Ease.OutBounce:反弹缓动,产生类似物体撞击墙壁后反弹的效果。
Ease.OutElastic:弹簧缓动,产生类似于物体被拉伸后回弹的效果。
自定义运动曲线
//运动曲线 public AnimationCurve curve; //自定义运动曲线 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).SetEase(curve);
//调用自己编写的曲线 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).SetEase(EaseFun); public float EaseFun(float time,float duartion,float overshootOrAmlitude,float period) { return time / duartion; }
回调函数
//动画被杀死的执行函数 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).OnKill(() => { Debug.Log(1); }); //开始运行的时候执行函数 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).OnPlay(() => { Debug.Log(1); }); //完成的时候执行函数 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).OnComplete(()=> { Debug.Log(1); }); //暂停的时候执行 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).OnPause(()=> { Debug.Log(1); }); //第一次运行动画的时候执行 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).OnStart(()=> { Debug.Log(1); }); //循环的时候执行 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).OnStepComplete(()=> { Debug.Log(1); }); //在这个动画的帧内都会被执行 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).OnUpdate(()=> { Debug.Log(1); }); //在动画重新播放的时候会被执行 transform.DOBlendableMoveBy(new Vector3(2, 5, 3), 5).OnRewind(()=> { Debug.Log(1); });
控制函数
//暂停 transform.DOPause(); //开始 transform.DOPlay(); //重新播放 transform.DORestart(); //回到起始位置(很快 transform.DORewind(); //回到起始位置(很慢 transform.DOSmoothRewind(); //杀死动画 transform.DOKill(); //反转动画,把起始点变为目标点 transform.DOFlip(); //代表跳转到动画第几秒 transform.DOGoto(2,true); //反向播放动画 transform.DOPlayBackwards(); //正向播放动画 transform.DOPlayForward(); //在运行状态下运行就是暂停,在暂停状态下运行就是播放 transform.DOTogglePause();
获取数据
//获得所有的暂停的动画 var list = DOTween.PausedTweens(); //获得所有在播放的动画 var list1 = DOTween.PlayingTweens(); //寻找Id为该字符串的动画,第二个参数代表获取当前播放的动画 var list2 = DOTween.TweensById("ID",true); //返回的是该动画上有什么缓冲下来的动画都会被收集下来 var list3 = DOTween.TweensByTarget(transform, true); //寻找这个动画是否有动画,第二个参数为true时,代表寻找该动画是否正在播放 var list4 = DOTween.IsTweening("id",true); //寻找所有正在播放的动画,包括延迟动画 var list5 = DOTween.TotalPlayingTweens(); //控制动画的播放的时间的指针 transform.DOMove(Vector3.one, 5).fullPosition = 0; var tween = transform.DOMove(Vector3.one, 5); //获取到该动画的循环次数 tween.CompletedLoops(); //获取动画的延迟时间 tween.Delay(); //动画的持续时间,参数代表是否包括循环的时间 tween.Duration(true); //动画的播放的时间,参数代表是否包括循环的时间 tween.Elapsed(); //返回的是进程的百分比 tween.ElapsedDirectionalPercentage(); //返回的是动画的已用的百分比,参数代表是否包括循环的时间 tween.ElapsedPercentage(); //判断动画是否是反向的 tween.IsBackwards(); //判断动画是否已经完成 tween.IsComplete();
携程
tween = transform.DOMove(Vector3.one, 2).SetLoops(3); StartCoroutine(Wait()); private IEnumerator Wait() { //等动画播放完再执行下面的语句 yield return tween.WaitForCompletion(); Debug.Log(0); //等待动画循环到第几次执行下面的语句 yield return tween.AsyncWaitForElapsedLoops(2); Debug.Log(1); //动画被杀时执行下面的语句 yield return tween.WaitForKill(); Debug.Log(2); //动画执行到该时间才会继续执行下面的方法 yield return tween.WaitForPosition(1.5f); Debug.Log(3); //动画重新播放的时候执行下面的方法 yield return tween.WaitForRewind(); Debug.Log(4); //动画开始执行的时候调用 yield return tween.WaitForStart(); Debug.Log(5); }
路劲动画
using System.Linq; //是将数组存放在positions里面 var positions = postionList.Select(u => u.position).ToArray(); //第一个参数是存放位置的数组,第二个参数是运行的时间,第三个参数是规定点之间是直线运行还是曲线运行 transform.DOPath(positions, 2); //将第一个位置和最后一个位置连起来,.SetOptions()的第一个参数是是否将首尾连接,第二个参数是锁定轴 //SetLookAt()里面的参数代表看向的位置,当参数是0该物体一直看向路径的前方,朝向针对运动方向的百分比从0-1 transform.DOPath(positions, 5, PathType.CatmullRom, PathMode.Full3D, 50).SetOptions(true).SetLookAt(0);