Unity DoTween DoTweenPath

参考
Unity 动画一:DOTween简单了解
Unity 动画二:DOTween使用简介
官网 http://dotween.demigiant.com/documentation.php
Unity Dotween常用方法详解
Unity插件之DOTween教程
演示效果可以看视频:https://www.bilibili.com/video/BV1BK411773V?p=23
DOTween源码解析

一、DOTween的性能优势

在一个循环中处理64000个通用浮点数:


image.png

在循环中处理4000个transform


image.png
二、写法
1、通用格式
image.png
//将myVector的值在1秒内,补间转换到(3,4,8)
DOTween.To(()=> myVector, x=> myVector = x, new Vector3(3,4,8), 1);

//将myFloat的值在1秒内,补间转换到52
DOTween.To(()=> myFloat, x=> myFloat = x, 52, 1);
2.快捷格式

DOTween包括一些已知的Unity对象的快捷方式,如Transform,Rigidbody和Material。 您可以从对这些对象的引用直接启动补间(这也将自动将对象本身设置为补间目标)

//将transform在1秒内移动到(2,3,4)的空间位置
transform.DOMove(new Vector3(2,3,4), 1);

//将rigidbody在1秒内移动到(2,3,4)的空间位置
rigidbody.DOMove(new Vector3(2,3,4), 1);

//将material的Color(颜色值)在1秒内渐变到绿色
material.DOColor(Color.green, 1);

无论您选择哪种方式,当创建一个补间时,都会返回一个Tweener或一个Sequence,可以根据实际需要保持这个引用,供之后使用。

三、控制方式

因为DOTween有多种写法和引用,所以控制DOTween的方式也有不少选择。以Rewind(回放)功能为例

1、静态调用:
//回放所有补间
DOTween.RewindAll();

//根据ID回放相关补间
DOTween.Rewind(myId);
2、通过引用
//通过myTween引用来回放
myTween.Rewind();
3、快捷调用
//回放transform上所有的补间动画
transform.DORewind();
4.FORM补间

顾名思义,FORM就是“从……来”的意思,即对应的最终值的部分就是变成了“初始值”。例如:

//常规补间To:将transform在1秒内,横向移动到2的位置
transform.DOMoveX(2, 1);

//FROM模式:将transform在1秒内,从2的位置移动到现在的位置
transform.DOMoveX(2, 1).From();

//FROM相对值模式:将transform在1秒内,从现在横向+2的位置,移动到现在的位置
transform.DOMoveX(2, 1).From(true);
5.链式设置SetEase SetLoops SetDelay

DOTween可以通过Set方法进行一系列的补间动画实现,通过On来进行回调。

//将transform在2秒内,移动到(2,2,2)位置,使用OutQuint的减速动画形式重复4次,动画结束后调用myFunction方法
transform.DOMove(new Vector3(2,2,2), 2)
.SetEase(Ease.OutQuint)
.SetLoops(4)
.OnComplete(myFunction);

//相同作用的另外一种写法

Tween myTween = transform.DOMove(new Vector3(2,2,2), 2);
myTween.SetEase(Ease.OutQuint);
myTween.SetLoops(4);
myTween.OnComplete(myFunction);
6.补间的生命周期 SetAutoKill

当您创建补间动画的时候,它通常是自动播放的,直到完成其所有循环内容后才会结束。但是,您可以更改全局属性defaultAutoPlay来控制。

当补间动画播放结束之后,通常是自动销毁的。但是,您可以更改全局属性defaultAutoKill来控制。如需要重复使用相同的补间动画,只要将autoKill设置为False便可,或者可以在设置补间动画的时候SetAutoKill(false)。

如果您没用使用安全模式,当补间动画实施的目标为空(null)时,可能会发生错误。

7.缓存和最大补间数量

如果您可以激活循环重用DOTween缓存,那么您就不必再额外创建新的对象了。

一般建议设置最大Tweener数量为200,最大Sequence数量为50。如果您需要更多功能,DOTween会自动增加两个的数量。但是,您可以直接设置,如下所示:

// 设置最大 Tweener数量为 3000 ,最大Sequence数量为 200
DOTween.SetTweensCapacity(3000, 200);

当要重置DOTween的缓存时,只需要调用DOTween.Clear()就可以了。

四、Transform拓展方法
1.position
//1)改变世界坐标
//移动方法,第一个参数是要移动到的目标点,不是移动这个向量的距离
transform.DOMove(new Vector3(1, 1, 1), 2);
//只控制x轴上的移动,其他两个方向同理
transform.DOMoveX(1, 2);
 
//2)改变局部坐标
transform.DOLocalMove(new Vector3(1, 1, 1), 2);
transform.DOLocalMoveX(1, 2);
2.rotation DOLookAt
//1)世界旋转
//旋转到给定的值,改变的是欧拉角
transform.DORotate(new Vector3(0, 90, 0), 2);
//旋转到给定的值,改变的是四元数
transform.DORotateQuaternion(new Quaternion(0.1f, 0.1f, 0.1f, 0.1f), 2);
        
//2)局部旋转
//旋转到给定的值,改变的是欧拉角
transform.DOLocalRotate(new Vector3(0, 90, 0), 2);
//旋转到给定的值,改变的是四元数
transform.DOLocalRotateQuaternion(new Quaternion(0.1f, 0.1f, 0.1f, 0.1f), 2);
        
//在给定时间内,平滑的让自身的z轴正方向指向目标点
transform.DOLookAt(new Vector3(0, 0, 0), 2);

第三个参数是旋转模式RotateMode mode = RotateMode.Fast

  • RotateMode.Fast:DoTween中旋转的默认模式,若无显示的指明旋转模式,那么此模式为当前旋转模式。但是使用此方法旋转,每次到了360就归0了,可以直接将endvalue设置为370试试,物体只会旋转10度。
  • RotateMode.FastBeyond360:超越360度,字面意思即可理解。同样设置370度,物体真的会从当前的度数,旋转到370度,且不会归零。
  • RotateMode.LocalAxisAdd:先从字面分析,local和上述讲的是一样的,基于自身当前旋转度数(localrotation)。add,是指在当前旋转度数的基础上增加endvalue的值。
  • RotateMode.WorldAxisAdd:直接分析world,是指相对于世界的旋转,若endvalue的值是(0,0,10),意思是以世界的z轴为方向,增加10度的旋转量。
3.Scale
//同上面一样,这里改变物体的缩放到目标值
transform.DOScale(new Vector3(2, 2, 2), 2);
//其他两个轴向同理
transform.DOScaleX(3, 2);
4.Punch 弹簧冲击
  • 第一个参数 punch:表示方向及强度
  • 第二个参数 duration:表示动画持续时间
  • 第三个参数 vibrato:震动次数
  • 第四个参数 elascity:
    这个值是0到1的
    当为0时,就是在起始点到目标点之间运动
    不为0时,会把你赋的值乘上一个参数,作为你运动方向反方向的点,物体在这个点和目标点之间运动
transform.DOPunchPosition(new Vector3(0, 1, 0), 2, 2, 0.1f);
transform.DOPunchRotation(new Vector3(0, 90, 0), 2, 2, 0.1f);
transform.DOPunchScale(new Vector3(2, 2, 2), 2, 2, 0.1f);
image.png
5.Shake 抖动
  • 参数:持续时间,力量,震动,随机性,淡出
  • 力量:实际就是震动的幅度,可以理解成相机施加的力的大小 使用Vector3可以选择每个轴向不同的强度
  • 震动:震动次数
  • 随机性:改变震动方向的随机值(大小:0~180)
  • 淡出:就是运动最后是否缓慢移动回到原本位置
transform.DOShakePosition(1, 5, 10, 50, true);
transform.DOShakeRotation(3);
transform.DOShakeScale(3);
6.Blend 混合动画

原本同时执行两个Move方法,只会执行最新的一个动画命令例如:

transform.DOMove(Vector3.one, 2);
transform.DOMove(Vector3.one* 2, 2);

结果是物体运动到了(2,2,2)坐标上

DOBlendableMoveBy方法有两个特点
1)允许多个同时执行
例如:

transform.DOBlendableMoveBy(new Vector3(1, 1, 1), 1);
transform.DOBlendableMoveBy(new Vector3(-1, 0, 0), 1);

假设起始点为(0,0,0),最后动画停止时的坐标就是(0,1,1)

2)它是增量动画

transform.DOBlendableMoveBy(new Vector3(1, 1, 1), 1);

假设起始点为(1,1,1),最后动画停止时的坐标就是(2,2,2)

它的参数不是目标点,而是要移动的量

以下三个函数同理

transform.DOBlendableRotateBy()
transform.DOBlendableScaleBy()
transform.DOBlendablePunchRotation()
7.DOJump 跳跃
        //物体的跳跃
        //transform.DOJump(new Vector3(60, 0, 0), 1, 5, 5f);
        //transform.DOLocalJump(new Vector3(60, 0, 0), 1, 5, 5f);
五、Material拓展方法
1.改变颜色
//material
Material material = GetComponent<MeshRenderer>().material;
material.SetColor("_Color", Color.red);//修改_Color值为red

这个的基础是物体的Shader中有Main Color这个属性的,没有的话不能改变,是有解决办法的

material.DOColor(Color.black, 2);
image.png

image.png
2.按照shader的属性名,修改颜色
material.DOColor(Color.clear, "_TintColor", 2);//""中的是颜色的名字
image.png
3. 修改alpha值
material.DOFade(0, 2);
//默认为_Color,如果没有,则需要添写第二个参数
material.DOFade(0, "_TintColor", 2);
4. 颜色渐变
//脚本中添加这个属性,在UNITY视图中就能选颜色渐变器
public Gradient _gradient;
Gradient是unity的渐变编辑器(下面有渐变编辑器的图)
material.DOGradientColor(_gradient, "_Color", 3);
image.png

image.png
5.改变材质offset的值,改变贴图的UV坐标
material.DOOffset(new Vector2(1, 1), 2);
image.png
6.改变提供的shader属性的名称对应的Vector4值
material.DOVector(new Vector4(0, 0, 0, 1), "_Color", 3);
7.颜色混合

跟位置混合动画同理,可以同时执行而不干扰,产生混合在一起的颜色

material.DOBlendableColor(Color.red, "_Color", 3);
material.DOBlendableColor(Color.yellow, "_Color", 3);
六、camera的拓展方法
1.调整屏幕视角的宽高比 第一个参数是(宽/高)的比值
Camera camera = GetComponent<Camera>();
camera.DOAspect(0.6f, 2);
20200305111549669.gif
2.改变相机background参数的颜色
camera.DOColor(Color.red, 2);
20200305111957914.gif
3.改变相机近切面的值
camera.DONearClipPlane(1, 2);
image.png

20200305112411515.gif
4.改变相机远切面的值
camera.DOFarClipPlane(700, 2);
image.png

20200305112801850.gif
5.改变相机FOV的值,放大镜效果
camera.DOFieldOfView(30, 2);
image.png

20200305133448522.gif
6.改变相机正交大小
camera.DOOrthoSize(10, 2);
image.png
7.按照屏幕像素计算的显示范围
camera.DOPixelRect(new Rect(0f, 0f, 800, 500f), 2);
20200305135528834.gif
8.按照屏幕百分比计算的显示范围
camera.DORect(new Rect(0.0f, 0.0f, 0.5f, 0.5f), 2);
image.png
9.相机震动

相机震动效果 参数:持续时间,力量,震动,随机性,淡出
力量:实际就是震动的幅度,可以理解成相机施加的力的大小 使用Vector3可以选择每个轴向不同的强度
震动:震动次数
随机性:改变震动方向的随机值(大小:0~180)
淡出:就是运动最后是否缓慢移动回到原本位置

camera.transform.DOShakePosition(1, 10, 10, 50, false);
20200305150457739.gif
七、Text拓展方法 (打字机效果)
Text text = GetComponent<Text>();
text.DOColor(Color.black, 2);//颜色
text.DOFade(0, 2);//透明度
text.DOBlendableColor(Color.black, 2);//颜色混合
 
第一个参数传入的内容按照时间,一个字一个字的输入到文本框中
//.SetEase(Ease.Linear)是按匀速打字
text.DOText("context", 2).SetEase(Ease.Linear);
八、Sequence

在实际的需求中,一个动画一般都包含对多个物体的操作,那么如何使用DoTween制作这种动画呢?对于一些简单的动画,直接顺序执行多个DoTween语句即可;对于一些复杂的动画,诸如包含延时、动画事件回调、播放音效等的动画,可以利用DoTween的动画队列完成这些操作。如果你有Cosos等2d引擎的使用经验,那么Sequence你一定不会陌生。

Sequence quence = DOTween.Sequence();
1.添加动画到队列中
quence.Append(transform.DOMove(-Vector3.one, 2));
2.添加时间间隔
quence.AppendInterval(1);
3.按时间点插入动画

第一个参数为时间点,此方法把动画插入到规定的时间点
以这句话为例,它把DORotate动画添加到此队列的0秒时执行,虽然它不是最先添加进队列的
在某时间点插入,和本身队列不冲突,同时进行

quence.Insert(0, transform.DORotate(new Vector3(0, 90, 0), 2));
20200306102631133.gif
4.join 加入当前动画

Join会加入和让动画与当前正在执行的动画一起执行
如下两行代码,DOMove会和DOScale一起执行

quence.Append(transform.DOScale(Vector3.one * 5, 2));
quence.Join(transform.DOMove(Vector3.one * 5, 2));
2020030610554663.gif
5.预添加动画

预添加 会直接添加动画到Append的前面,也就是最开始的时候

quence.Prepend(transform.DOScale(Vector3.one * 0.5f, 1));

这里需要特别说一下预添加的执行顺序问题
它这里也采取了队列的性质,不过,预添加与原本的的队列相比是一个反向队列
例如:

quence.Append(transform.DOMove(Vector3.one, 2));
quence.Prepend(transform.DOMove(-Vector3.one * 2, 2));
quence.PrependInterval(1);

执行顺序是 PrependInterval----Prepend---- - Append
就是最后添加的会在队列的最顶端

6.预添加时间间隔
quence.PrependInterval(1);
7.回调函数
//1)预添加回调,直接添加到最开始的时候
quence.PrependCallback(PreCallBack);

//2)在规定的时间点加入回调
quence.InsertCallback(0, InsertCallBack);

//3)添加回调
quence.AppendCallback(CallBack);
 
private void PreCallBack()
{
    Debug.Log("PreCallBack");
}
 
private void InsertCallBack()
{
    Debug.Log("InsertCallBack");
}
 
private void CallBack()
{
    Debug.Log("CallBack");
}

AppendCallback 当前执行的队列动画完成后自动调用
InsertCallbakc 它的执行时间点只跟他填写的时间参数有关

九、动画设置 TweenParams
TweenParams para = new TweenParams();
1.设置动画循环
  • 第一个参数是循环次数 - 1代表无限循环
  • 第二个参数是循环方式
  • Restart 重新开始
  • Yoyo 从起始点运动到目标点,再从目标点运动回来,这样循环
  • Incremental 一直向着运动方向运动
para.SetLoops(-1, LoopType.Yoyo);
2.设置参数
transform.DOMove(Vector3.one, 2).SetAs(para);
3.设置自动杀死动画

参数:false会缓存,true会直接释放

transform.DOMove(Vector3.one, 1).SetAutoKill(true);
4.from补间,从目标点移动到当前点
transform.DOMove(Vector3.one, 2).From(true);

From参数 isRelative(相对的):

  • 为true,传入的就是偏移量,即当前坐标 + 传入值 = 目标值
  • 为falese,传入的就是目标值,即传入值 = 目标值
5.设置动画延时
transform.DOMove(Vector3.one, 2).SetDelay(1);
6.设置动画运动以速度为基准

使用SetSpeedBased时,移动方式就变成以速度为基准
原本表示持续时间的第二个参数,就变成表示速度的参数,每秒移动的单位数

transform.DOMove(Vector3.one, 1).SetSpeedBased();
7. 设置动画ID

可以调用缓存的动画

transform.DOMove(Vector3.one, 2).SetId("Id");
DOTween.Play("Id");
8.设置是否可回收

为true的话,动画播放完会被回收,缓存下来,为false播完就直接销毁

transform.DOMove(Vector3.one, 2).SetRecyclable(true);
9.设置动画为增量运动

SetRelative参数 isRelative(相对的):

  • 为true,传入的就是偏移量,即当前坐标 + 传入值 = 目标值
  • 为falese,传入的就是目标值,即传入值 = 目标值
transform.DOMove(Vector3.one, 2).SetRelative(true);
10.设置动画的帧函数

第一个参数 UpdateType: 选择使用的帧函数

  • UpdateType.Normal:更新每一帧中更新要求。
  • UpdateType.Late:在LateUpdate调用期间更新每一帧。
  • UpdateType.Fixed:使用FixedUpdate调用进行更新。
  • UpdateType.Manual:通过手动DOTween.ManualUpdate调用进行更新。

第二个参数:为TRUE,则补间将忽略Unity的Time.timeScale

transform.DOMove(Vector3.one, 2).SetUpdate(UpdateType.Normal, true);
十、Ease 运动曲线的设置
1. 以Ease枚举作为参数

Dotween Ease效果演示地址
http://robertpenner.com/easing/easing_demo.html

20200307090708205.gif

//匀速运动
transform.DOMove(Vector3.one, 2).SetEase(Ease.Linear);

transform.DOMove(Vector3.one, 2).SetEase(Ease.Flash, 3, 0f);

第二个参数 Amplitude(振幅):实际就是移动次数,起始点移动到目标算移动一次,再移动回来移动两次
第三个参数 period 值的范围是 -1~1

  • 值 > 0时,为活动范围的衰减值,活动范围会由大变小
  • 值 = 0时,就是均匀的在起始坐标和目标坐标之间运动
  • 值 < 0时,会施加一个向目标坐标的一个力,活动范围一点点增大,最后逼近目标点

这两个参数只对Flash, InFlash, OutFlash, InOutFlash这四种曲线有用,其他的曲线起作用的就只有Ease枚举参数

2.使用AnimationCurve组件当作参数
image.png

image.png

AnimationCurve 横轴是时间, 不过不是具体的时间,而是时间比例
AnimationCurve 纵轴是倍数,即(起始点和目标点距离)*倍数
假设纵轴的值为v,传入DOMove的第一个参数endValue是e,起始点坐标是s
此物体最后动画结束时的实际坐标即为 v * (e - s)+s

transform.DOMove(Vector3.one * 2, 1).SetEase(curve);
3. 以回调函数为参数
transform.DOMove(Vector3.one * 2, 1).SetEase(MyEaseFun);

返回值是运动距离的百分比 值应为0~1之间,0为起点,1为终点,不然停留的位置不会是目标位置
参数:1、当前动画运行的时间,2、持续时间

return time / duration : 0-1 (1,1,1) 1
return time / duration + 1 : 1-2 (2,2,2) (3,3,3)
private float MyEaseFun(float time, float duration, float overshootOrAmplitude, float period)
{
    return time / duration + 1;
}
4.回调函数
1)动画完成回调
transform.DOMove(Vector3.one, 2).OnComplete(() => { Debug.Log("完成"); });
 
2)动画被杀死时回调
transform.DOMove(Vector3.one, 2).OnKill(() => { });
 
3)动画播放时回调,暂停后重新播放也会调用
transform.DOMove(Vector3.one, 3).OnPlay(() => { });
 
4)动画暂停时回调
transform.DOMove(Vector3.one, 2).OnPause(() => { });
 
5)动画回退时回调
以下情况会被调用
使用DORestart重新播放时
使用Rewind倒播动画完成时
使用DOFlip翻转动画完成时
使用DOPlayBackwards反向播放动画完成时
transform.DOMove(Vector3.one, 2).OnRewind(() => { });
 
6)只在第一次播放动画时调用,在play之前调用
transform.DOMove(Vector3.one, 2).OnStart(() => { });
 
7)完成单个循环周期时触发
transform.DOMove(Vector3.one, 2).OnStepComplete(() => { });
 
8)帧回调
transform.DOMove(Vector3.one, 2).OnUpdate(() => { });
 
9)在路径动画时,改变目标点时的回调,参数为当前目标点的下标
transform.DOMove(Vector3.one, 2).OnWaypointChange((value) => { });
5.动画控制方法
1)播放
transform.DOPlay();
 
2)暂停
transform.DOPause();
 
3)重播
transform.DORestart();
 
4)倒播,此方法会直接退回起始点
transform.DORewind();
 
5)平滑倒播,此方法会按照之前的运动方式从当前位置退回起始点
transform.DOSmoothRewind();
 
6)杀死动画
transform.DOKill();
 
7)翻转补间的方向,起始点变目标点
transform.DOFlip();
 
8)跳转时间点
第一个参数跳转的时间点,第二个参数是跳转后是否播放动画
transform.DOGoto(1.5f, true);
 
9)反向播放动画
反向播放动画,在动画播放到一半时执行,会退回起始点,在一开始执行看不到效果是因为,物体本身就在起始点
transform.DOPlayBackwards();
 
10)正向播放动画
transform.DOPlayForward();
 
11)TogglePause
当暂停时,执行就继续播放,播放时,执行就暂停
transform.DOTogglePause();
6.获取类方法

1)返回所有暂停的动画,没有则返回null

List<Tween> list = DOTween.PausedTweens();

2)返回所有真正播放的动画,没有则返回null

List<Tween> list = DOTween.PlayingTweens();

3)获取给定ID的数组
返回满足条件的动画数组
第一个参数是动画的ID
第二个参数是是否只收集正在播放的动画,因为DOTween会缓存之前播放过的动画

List<Tween> list = DOTween.TweensById("id", true);

4)返回给定对象的数组
返回满足条件的动画数组
第一个参数是播放动画的对象
例如:transform.DOMove(Vector3.one, 2); 第一个参数就传入transform
material.DOColor(Color.White, 2); 第一个参数就传入材质对象material
第二个参数是是否只收集正在播放的动画

List<Tween> list = DOTween.TweensByTarget(transform, true);

5)收集传入的对象是否有动画在活动
第一个参数为检测的 (对象 或 ID)
第二个参数为是否检测动画在播放状态
为true时,给定对象在播放状态时,延时状态也算正在播放 返回true
为false时,只检测给定对象是否有动画(在pause状态时也算)有则返回true

List<Tween> list = DOTween.IsTweening(transform,true);

6)正在播放的动画的总数,目前处于延迟播放状态的动画也算

int num = DOTween.TotalPlayingTweens();
7.获取实例方法
Tween _tweener = transform.DOMove(Vector3.one, 1).SetLoops(3);

//1)表示动画执行时间的属性,可读可写,是设置动画的进度
_tweener.fullPosition = 1;//设置动画的时间点为1秒
 
//2)表示动画执行完的次数(包括循环),配合.OnStepComplete(() => { })使用
int num = _tweener.CompletedLoops();
 
//3)获取动画的延迟时间
float time = _tweener.Delay();
 
//4)获取动画的持续时间
//参数为true 表示计算循环的时间,无限循环返回Infinity,flase不包括循环的时间
float time = _tweener.Duration(false);//flase返回1,true返回3
 
//5)动画已播放的时间
//参数为true 表示计算循环的时间
float time = _tweener.Elapsed();//false返回0-1,true返回0-3
 
//6)返回动画进度的百分比
//起始点为0 目标点为1 当yoyo循环模式下,值会从0变到1再从1变到0
float percent = _tweener.ElapsedDirectionalPercentage();
 
//7)返回动画区间已用的百分比
//单次循环的数值为0到1
//参数为 是否包含循环 为true时 返回值是循环总区间的已用百分比 若为无限循环 返回值为0
transform.DOMove(Vector3.one, 1).SetLoops(3) // false时总里程为1,true时总里程为3
_tweener.ElapsedPercentage(true);
 
//8)动画是否在活动
_tweener.IsActive();
 
//9)是否是反向动画
_tweener.IsBackwards();
 
//10)动画是否完成
_tweener.IsComplete();
 
//11)是否以初始化
_tweener.IsInitialized();
 
//12)是否正在播放
_tweener.IsPlaying();
 
//13)返回循环次数,无限循环为Infinity
_tweener.Loops();
8.协程方法
private Tweener _tweener;
 
void Start () 
{
    _tweener = transform.DOMove(Vector3.one * 2, 1).SetLoops(3);
    StartCoroutine(Wait());
}
 
private IEnumerator Wait()
{
    //1)等待动画执行完
    yield return _tweener.WaitForCompletion();
 
    //2)等待指定的循环次数
    //参数为执行次数,等待传入的循环次数后,继续执行
    //若是传入的次数大于动画的循环次数 则在动画结束时继续执行
    yield return _tweener.WaitForElapsedLoops(2);
 
    //3)等待动画被杀死
    yield return _tweener.WaitForKill();
 
    //4)等待动画执行指定时间
    //参数为时间,动画执行传入的时间之后或动画执行完毕,继续执行
    yield return _tweener.WaitForPosition(0.5f);
 
    //5)等待动画回退
    //以下情况会继续执行函数
    //使用DORestart重新播放时
    //使用Rewind倒播动画完成时
    //使用DOFlip翻转动画完成时
    //使用DOPlayBackwards反向播放动画完成时
    yield return _tweener.WaitForRewind();
 
    //6)等待Start执行后继续执行
    yield return _tweener.WaitForStart();
}
十一、路径动画

Dotween对于路径动画就只提供了两个方法,一个是针对于世界坐标的,一个是针对于局部坐标的,本质上没啥区别,就以世界坐标的方法为例,进行讲解


image.png
  • waypoints: 是提供路径上点的坐标,需要按顺序添加进数组
  • duration:路径动画的整体持续时间
  • pathType:路径类型(就是点于点之间路径连线的生成方式)
         它内部预定义了两种类型
          Linear:直线
          CatmullRom:曲线
  • pathModel: 路径模式(用于确定正确的LookAt方向)
         它内部定义了四种类型
          Ignore:忽略此参数和设置的LookAt参数
          Full3D:在3d场景下,代表物体可以看向任何方向
          TopDown2D:代表物体只能上下旋转,看向物体
          Sidescroller2D:代表物体只能左右旋转看向物体
  • resolution:路径分辨率,代表路径点之间的曲线由多少个点构成,也就是点越多,曲线就越圆,此参数在直线路径类型下无效
  • gizmoColor:在Scene视图中,生成的路径曲线的颜色
public Transform[] PointList;//所有的路径点
void Start () {
    //Transform数组转换成vector数组
    var positions = PointList.Select(u => u.position).ToArray();
    transform.DOPath(positions,5,PathType.CatmullRom,PathMode.Full3D,50,Color.blue);
}
1.SetOptions
image.png
  • closePath:是否是封闭路径,设为true的话,会形成闭环,最后运动回起点
  • lockPosition:锁定位置,参数为轴向,例如,填入AxisConstraint.X的话,横向的位移将被锁定,物体只能在其他方向上移动
  • lockRotation:锁定旋转,参数为轴向,和锁定位置同理,锁定的轴向不能旋转
2.SetLookAt
image.png

这个方法是很重要的方法,它的后两个参数,是提供看向的轴向,一般很少更改,就不介绍了,主要介绍第一个参数
它针对于第一个参数的改变,有三种重载
  (1)Transform类型参数 lookAtTransform:也就是要看向的物体
  (2)Vector3类型参数 lookAtPosition:也就是要看向的位置
  (3)float类型的参数 lookAhead:一个向路径的前方看的参数
前两个很容易理解,就不多说了,主要说一下第三种 lookAhead

3.lookAhead 参数

这个参数的取值范围是0到1的
首先说明,它值的变化,产生的效果


image.png

这个值的变化,决定了物体开始移动时的朝向。这个参数在不同数值下的效果,受到SetOptions的第一个参数closePath影响。比较通俗的解释:
(1)closePath为false (运动最后,物体的朝向移动是路径的运动方向的前方)
lookAhead = 0:目标会沿着路径看向前方
lookAhead != 0:目标会按照参数,决定开始运动时的朝向,但是运动期间会匀速转动朝向,最后朝向会转回路径前方的朝向

(2)closePath为true(开始时确定方向后就不会变化了)
lookAhead = 0:目标会沿着路径看向前方
lookAhead >0 && lookAhead <1:一直保持开始时的方向(即如上图所示)
lookAhead = 1:这个时候,SetLookAt没有效果,即物体不会改变朝向

这里所说的朝向是相对于运动路径的朝向

总结:

  • lookAhead 参数的意思就是 看前看的偏移量
  • 假设整个路径normalize. 即开始点为0,结束点为1. 走到路程的一半即为0.5.
  • 所以如果lookAhead = 0.5 时, 假设当前Transform行走进程到 0.1的位置,则会 LookAt 行走进程 0.6的位置.
  • 如果closePath=true, 则 lookAtPercent = Mathf.Repeat(movePercent + lookAhead, 1);
  • 否则closePath=false, 则 lookAtPercent = Mathf.Clamp01(movePercent + lookAhead);
十二、DoTweenPath

参考Unity之DOTweenPath轨迹移动

AddComponent

下面是一些复杂属性的解释

1.Loops
image.png

Loops:循环次数,动画循环播放的次数

  • -1:表示 一直循环
  • 0:表示只播放一次
  • 当该值>1时,检视面板出现LoopType,顾名思义就是指循环类型:
    • Restart:重新开始,后面的动画循环播放会从起点重新开始;
    • Yoyo:来回播放
    • Incremental:增加的,后面的path移动动画会在上一次循环的终点的基础上进行播放
2.ID
image.png

可以设置成一个统一的ID,然后统一KILL掉

public readonly string TweenID_Game = "Game";//所有游戏dotweenID
...
DOTween.Kill(Constant.tweenID.TweenID_Game);

参考使用DOTweenPath中的ID进行调取执行DOTweenPath
可以遍历物体上面所有的DOTweenPath,通过ID找到自己想要的那一个。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
public class NewBehaviourScript : MonoBehaviour
{
    public DOTweenPath[] doTween;

    void Start()
    {
        cleanAllColliders(this.transform);
    }
    void cleanAllColliders(Transform ga)
    {
        doTween = GetComponents<DOTweenPath>();
        foreach (DOTweenPath cc in doTween)
        {
            Debug.Log(cc.id);
        }
    }
}
3.UpdateType

transform.DOMove(Vector3.one, 2).SetUpdate(UpdateType.Normal, true);是一样的
第一个参数 UpdateType: 选择使用的帧函数

  • UpdateType.Normal:更新每一帧中更新要求。
  • UpdateType.Late:在LateUpdate调用期间更新每一帧。
  • UpdateType.Fixed:使用FixedUpdate调用进行更新。
  • UpdateType.Manual:通过手动DOTween.ManualUpdate调用进行更新。
3.Path Tween Options
image.png
  • Linear:线型的
  • Catmull Rom:曲线
  • Close Path:封闭曲线,将起点和终点相连
  • Lock Rotation:锁旋转,xyzw

Path Mode参见上面的第十一、路径动画

  • Ignore:忽略此参数和设置的LookAt参数
  • Full3D:在3d场景下,代表物体可以看向任何方向
  • TopDown2D:代表物体只能上下旋转,看向物体
  • Sidescroller2D:代表物体只能左右旋转看向物体
4.Events:
  • OnStart:开始时
  • OnPlay:播放时
  • OnUpdate:更新时
  • OnStep:单步完成时
  • OnComplete:完成时
  • OnCreated:动画创建时

事件顺序为:OnCreated->OnStart->OnPlay->OnUpdate(一直执行,直到完成),动画过程中单步完成时执行OnStep,整个动画完成后执行OnComplete。


这里哪个绿了表示激活哪个事件
5.WayPoints:移动轨迹点
image.png

按住SHIFT+CTRL,然后在场景中点击,即可添加路点。同理,SHIFT+ALT则是删除路点。
其中右边的Copy to clipboard,将坐标复制至剪贴板。

6.动态路径

Unity3d使用DOTween实现动态路径方法DOPath和DOTweenPath无效情况
有个项目有如题的需求,主要是能给对象动态的设定路径,并执行延路径运动的动画。路径上的点是动态生成的,而且路径可能不唯一。

总结
DOPath可以直接设置路径点和动画时间,实现执行动态路径的动画。
DOTweenPath不知道可不可行,目前测出的暂时没成功。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容

  • 一、Unity简介 1. Unity界面 Shift + Space : 放大界面 Scene界面按钮渲染模式2D...
    MYves阅读 8,177评论 0 22
  • 面试题总分类 --------------------------------------- |--继承,封装,多...
    浪荡少年阅读 8,334评论 0 8
  • 1.命名前缀DO: 动作操作前缀。 例如:DoMove(),DoKill()等等。 Set:动画设置操作前缀。例如...
    胤醚貔貅阅读 2,421评论 1 3
  • 111. [动画系统]如何将其他类型的动画转换成关键帧动画? 动画->点缓存->关键帧 112. [动画]Unit...
    胤醚貔貅阅读 12,955评论 3 90
  • 素材管理 可以直接将图片(Gif)、声音(mp3)、动画、文字等素材从资源浏览器拖动到库中。 资源Url UIPa...
    崧泽阅读 850评论 0 0