学习目标:
今天来介绍一下Unity的一个好插件DOTween,也就当复习巩固了,没想到在B站上看到了一个远古视频有老师教学怎么使用DOTween,于是在学习了42P视频后就讲学到的常用函数属性给大伙看一遍。
如果有懂哥的话肯定知道这个插件大致就是通过代码控制住动画,让游戏运行的时候能进行相应的动画,下列是公司说的优点
然后我们在Asset Store下载一个免费版的,然后倒入到Unity中
右下角Import一下,
导入成功后就会看到这个绿色按钮点一下等一会Apply成功后即可退出,DOTween插件成功导入。然后我们还可以在代码中引用它的命名空间了。
准备好了话就先创建一个3D 的项目,然后开始每个方法都要实践吧。
学习内容:
红色注意:要使用它的命名空间要在一开始的using下添加命名空间using DG.Tweening;
除非特殊说明,不然所有代码都是在Untiy自带的Start()函数上完成的。
一:首先从移动和旋转,大小开始
//transform.DOMove(Vet3目标点,float时长)
//transform.DOMove(Vector3.one, 2f);
//transform.DOMoveX() //移动x轴
//transform.DOLocalMove() Unity中有自身坐标(相对)以及世界坐标(绝对)
还有另一种Punch的可以让你的移动反复(一般震动和弹性都是用默认的)
//DOPunchPosition反复开始和结尾的位置
//transform.DOPunchPosition(new Vector3(0, 1, 0),2f,3,0.1f); //Vet3 时间 震动 弹性
//DORotate(Vet3目标度数,float时长)
//transform.DORotate(new Vector3(50, 50, 50), 2f);
//DOScale(Vet3目标大小,float时长)
//transform.DOScale(new Vector3(2, 2, 2), 2f);
然后还有一个震动的
//震动的时长,强度,频率,随机的角度
//transform.DOShakePosition(2f, 4, 10, 90);
二丶材质部分
我们还可以用于修改材质
首先创建一个3D Object 叫Cube,然后创建一个Material,再将照片给它
可以见到我们两种Shader都用的不一样的
如果我们用Patricals的,则啊草图片是显示不出来的。
下面是Standard
扯的有点远了,首先我们用回第一张图的Shader,然后我们开始介绍代码
//材质
Material material = GetComponent<MeshRenderer>().material;
//DOColor(Color你想要改变的颜色,把颜色赋值给Shader属性的Color(默认"_Color",看你用的是什么shader了),时长)
//material.DOColor(Color.red,"_TintColor", 2);
那么这个_TintColor在哪里看呢?就在你的材质里,找到Color的名字后复制粘贴进去,不然会报错的(Standard则没有这种问题)点击Edit,可以看到它的属性
//修改透明度第一方法:DOColor()将颜色清零
//material.DOColor(Color.clear, "_TintColor", 2f);
//修改透明度第二方法:DOFade(Float Fade你想要改变的透明度大小,把颜色赋值给Shader属性的Color(默认"_Color",看你用的是什么shader了),时长)
//material.DOFade(0, "_TintColor", 2f);
如果要修改颜色的渐变值,首先我们要在回调函数外声明一个Grandient类
public Gradient gradient;//渐变
//渐变颜色DOGradientColor(Gradient 要渐变的,指定的属性, float时长)
//material.DOGradientColor(gradient, "_TintColor", 2);
材料的纹理坐标指的是Offset
可以改变它的Offset让Material有个滚动的效果
//纹理偏移值DOOffset(Vec2 Offset,float 时长)
//material.DOOffset(new Vector2(1, 1), 2);
我们还有一个混合模式,如果你只是单纯的列两条函数,那它只会执行后一条
//这两行最终执行结果也只是变为绿色
//material.DOColor(Color.red,"_TintColor", 2);
//material.DOColor(Color.green, "_TintColor", 2);
但你用了混合模式就不一样了,它会选择两种颜色的中间色
//材质的混合模式
material.DOBlendableColor(Color.red, "_TintColor", 2);
material.DOBlendableColor(Color.green, "_TintColor", 2);
三丶摄像机属性相关的动画
再声明一遍,如果你想要使用这些扩展函数的话,一定要引用命名空间
using DG.Tweening;
首先我们创建一个脚本挂载到摄像机上,再获取Camera组件,
Camera cam = GetComponent<Camera>();
//设置摄像机宽高比cam.DOAspect(float 宽高比值,float 时长)
//cam.DOAspect(1.5f, 2);
//设置摄像机的背景颜色(Color 你要变换的颜色,float 时长)
//cam.DOColor(Color.red, 2f);
//设置摄像机的近切面和远切面(Clipping Plane)Near,Far
//cam.DONearClipPlane(1.4f, 2f);
//cam.DOFarClipPlane(5f, 2f);
点开摄像机其实是这里
//设置Perspective摄像机的视域Fiew of View
//DOFieldOfView(float size,float 时长)
//cam.DOFieldOfView(100f, 2f);
//cam.DOOrthoSize()调整正交摄像机otherographic的视域大小
//cam.DOOrthoSize(6f, 2f);
这里涉及到摄像机的两种透视模式
//设置摄像机在屏幕的比例cam.DORect(Rect 矩形,float时长)
//cam.DORect(new Rect(0, 0, 0.5f, 0.5f),2f);
//根据像素设置摄像机在屏幕的比例
cam.DOPixelRect(new Rect(0, 0, 512, 384), 2f);
这里则是摄像机能在屏幕上显示的比例(一种是多少比例,一种是多少个像素)
我用的是1024:768个像素比
设置摄像机抖动这个是最常见的:
//设置相机的震动(float时长,float 强度,int 频率,float 随机度数)
cam.DOShakePosition(2);
四丶UI部分
可以看到这个DOTween真的已经覆盖了Unity组件的大部分。
首先是Text我们可以让Text像打字机一样输出文字,后面的SetEase()函数表示我们可以使用什么类型的模式来输出,每一种大伙都可以试一下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class TextDOTween : MonoBehaviour
{
void Start()
{
Text text = GetComponent<Text>();
//text.DOText(string,float).SetEase(样式)
text.DOText("abcdefghijklmnopqrstuvwxyz", 5f).SetEase(Ease.Linear);
}
}
同样,我们也可以用在Button上
这里简单写一点了,比如直接创建一个脚本然后挂载在一个新建的Button上,当触发点击事件的时候回进行反复移动
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class ButtonDOTween : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void aniBtn()
{
transform.DOPunchPosition(new Vector3(0, 20, 0), 0.4f,6,0.3f);
transform.DOPunchScale(new Vector3(0.3f, 0, 0), 0.3f, 4, 0.4f);
}
}
截的不是很好,但可以看出按钮已经播放动画了。
五丶(核心部分)运动序列
之所以我称呼他为核心部分,是因为它可以为某个动画添加各种一样行为,顺序逆序
首先我们先创建一个运动队列
运动队列本身就是一个队列,它所创建的所有序列都遵循队列的先进先出的顺序
Sequence sequence = DOTween.Sequence();
sequence.Append(transform.DOMove(Vector3.one, 2f));//0-2
//在上一个动作的基础上再加一个动作Join(Tween 动作)
//插入在某一时刻插入某个动作Insert(flaot 时刻,Tween 动作)
//sequence.Insert(0, transform.DOMove(-Vector3.one, 1.5f)); //从第0秒开始,就把一开始的Apeend给替换掉了
sequence.InsertCallback(2, appCallBack);
private void appCallBack()
{
Debug.Log("InsertCallBack");
}
sequence.Join(transform.DOScale(Vector3.one * 2, 2f));
//下列这两步和上面的Join一样
//sequence.Insert(0f, transform.DOScale(Vector3.one * 2, 2f));
//sequence.Insert(3f, transform.DOScale(Vector3.one, 2f));
//sequence.AppendCallback(); 回调函数
//我们现在Start()外面创建一个函数
private void appendCallBack()
{
Debug.Log("AppendCallBack");
}
然后就可以调用它了
sequence.AppendCallback(appendCallBack);
接下来介绍反过来的添加动作Prepend预添加Prepend则是一个栈 后进先出的
执行的顺序是先执行Prepend,再执行Append
sequence.PrependInterval(1f); //等待一秒
sequence.Prepend(transform.DOMove(-Vector3.one, 2f)); //先反方向
sequence.PrependCallback(prependCallBack);
private void prependCallBack()
{
Debug.Log("PrependCallBack");
}
这些是先执行的。
六丶运动参数TweenParams
也是挺重要的,标记为紫色。
首先要创建一个对象
TweenParams tp = new TweenParams();
然后是设置循环,第一个参数是循环的次数(如果是-1则代表无限循环,后面是循环的类型有Yoyo,Restart等)
TweenParams tp = new TweenParams();
//tp.SetLoops(-1, LoopType.Yoyo);
给一个动作赋予参数(通常bool值为false)
//transform.DOMove((Vector3.one), 1f).SetAs(tp).SetAutoKill(); //SetAutoKill()动作完成时自动销毁
//transform.DOMove((Vector3.one), 1f).From(true); //From(bool 基于方向进行移动,如果两个点重合的话,如果设置为true 即使两个点重合还会根据方向移动过来,如果都是(1,1,1)),他会从
//设置延迟参数
//transform.DOMove(Vector3.one, 1).SetDelay(3f);
//设置速度(DOMove里面的数字10就是速度)
//transform.DOMove(Vector3.one, 10).SetSpeedBased(true); //SetSpeedBased(bool true则是速度,false则是时间)
通过ID来编号你要执行的动作
//设置 SetId(string ID名字)
//transform.DOMove(Vector3.one, 2f).SetId("ID03");
//DOTween.Play("ID03");
//设置可回收的
//transform.DOMove(Vector3.one, 2f).SetRecyclable();
//设置增量的使用
//transform.DOMove(Vector3.one, 2f).SetRelative();
//SetUpdate(UpdateType Upadte的类型Normal则是通常的,bool 播放的时间帧值true则不受Time.scaletime控制)
//transform.DOMove(Vector3.one, 2f).SetUpdate(UpdateType.Normal,true);
//Linear匀速 Flash闪动 float 10速度的变换
//transform.DOMove(Vector3.one, 2f).SetEase(Ease.Linear,10,0);
自定义曲线,首先要在开头声明一个
public AnimationCurve ac;
可以看到在Inspector面板上我们点击后可以选择你的曲线,也可以通过鼠标右键点击Add Key来添加属性让曲线呈现你想要的。
//自定义曲线Easer、
//transform.DOMove(Vector3.one, 2).SetEase(ac);
你也可以自定义一个函数来绘制曲线
//自定义函数型曲线
//transform.DOMove(Vector3.one, 2).SetEase(MyEaseRun);
private float MyEaseRun(float time, float duration, float overshootOrAmplitude, float period)
{
return time / duration;
}
八丶回调函数
DOTween上的回调函数同样也是非常重要的内容。
例如我们可以用Lamada表达式来创造动作完成时候的回调
//Lamada表达式OnComplete
//transform.DOMove(Vector3.one, 2f).OnComplete(() => { Debug.Log("kkjjj"); });
除此之外还有其他的,与Unity的MonoBehavior自带的回调函数相似知识在前面加了个on
还有一个输出动作的时间点fullPosition这里以异步为例
接下来介绍fullPosition,这里引用异步函数,首先先声明两个命名空间
using System;
using System.Threading.Tasks;
async void Start()
{
var tweener = transform.DOMove(Vector3.one, 2f);
await Task.Delay(TimeSpan.FromSeconds(1));
//tweener.fullPosition = 2; //如果是2,则表示暂停线程1秒后直接到达2秒的位置
Debug.Log(tweener.fullPosition); //返回的是当前位置是在总时间的第几秒
//动画的时间时刻tweener.fullPosition;
}
可以看到它通过当前位置计算出方块的位置相当于总时间的多少秒
等我们把注释解掉,仅有一秒就运行到本来动画2秒就要运行到的位置
//var tweener = transform.DOMove(Vector3.one, 1f).SetLoops(3);
//获取有多少个暂停动画tweener.Delay();
//执行的时间tweener.Duration(bool 是否包含循环) false则是总时长(1),true则要乘以循环次数(1*3);
//已经执行完成的时间tweener.Elapsed(bool 是否包含循环) false则是总时长(1),true则要乘以循环次数(1 * 3));
//动画的播放进度[0,1]tweener.ElapsedDirectionalPercentage()
//tweener.ElapsedPercentage(bool); //也有判断是否包含循环
//可以看是否包括循环,如果是则返回整体循环的百分比 tweener.ElapsedPercentage(bool);
//返回循环次数tweener.Loops();
//await Task.Delay(TimeSpan.FromSeconds(1));
//Debug.Log(tweener.CompletedLoops());
//await Task.Delay(TimeSpan.FromSeconds(1));
//Debug.Log(tweener.CompletedLoops());
//await Task.Delay(TimeSpan.FromSeconds(1));
//Debug.Log(tweener.CompletedLoops());
//transform.DORestart();
//transform.DORewind(); //重新回到开始位置
//transform.DOSmoothRewind();// 平滑的重新回到开始位置
//transform.DOPause(); //暂停
//transform.DOPlay(); //播放
//transform.DORestart(); //重新开始
//await Task.Delay(TimeSpan.FromSeconds(1)); //延迟人物,把秒转化为毫秒TimeSpan.FromSeconds
//transform.DORewind(); //回到开始的位置
//transform.DOSmoothRewind();
//transform.DOFlip();
//transform.DOGoto(1,true); //float跳到那个时间点,bool 是否继续播放
//transform.DOPlayForward();
//transform.DOPlayBackwards();
//transform.DOTogglePause(); //暂停一瞬间感觉没什么用
//await Task.Delay(TimeSpan.FromSeconds(1));
//transform.DOTogglePause();
九丶类方法
用于统筹你的之前创造的动画动作等。
//transform.DORestart();
//transform.DORewind(); //重新回到开始位置
//transform.DOSmoothRewind();// 平滑的重新回到开始位置
//transform.DOPause(); //暂停
//transform.DOPlay(); //播放
//transform.DORestart(); //重新开始
//await Task.Delay(TimeSpan.FromSeconds(1)); //延迟人物,把秒转化为毫秒TimeSpan.FromSeconds
//transform.DORewind(); //回到开始的位置
//transform.DOSmoothRewind();
//transform.DOFlip();
//transform.DOGoto(1,true); //float跳到那个时间点,bool 是否继续播放
//transform.DOPlayForward();
//transform.DOPlayBackwards();
//transform.DOTogglePause(); //暂停一瞬间感觉没什么用
//await Task.Delay(TimeSpan.FromSeconds(1));
//transform.DOTogglePause();
十丶协程
协程与进程不同,一个应用程序一般对应一个进程,一个进程一般有一个主线程,还有若干个辅助线程,线程之间是平行运行的,在线程里面可以开启协程,让程序在特定的时间内运行。(引用文章:
unity 协程原理与线程的区别_天涯过客TYGK的博客-CSDN博客_协程与线程的区别
https://blog.csdn.net/u011484013/article/details/51136780?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165209865816782246448450%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165209865816782246448450&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-51136780-null-null.142%5Ev9%5Econtrol,157%5Ev4%5Econtrol&utm_term=unity%E5%8D%8F%E7%A8%8B%E5%92%8C%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%8C%BA%E5%88%AB&spm=1018.2226.3001.4187
)是Unity独特的,利用计数器IEnumerator和StartCorountine来调用协程
只不过看到这里的应该都是大多懂Unity协程的运行进程的,所以我就不细讲了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
public class IEnumeratorDOTween : MonoBehaviour
{
Tween twn;
void Start()
{
twn = transform.DOMove(new Vector3(2, 2, 2), 2f).SetLoops(3,LoopType.Yoyo);
StartCoroutine(waitFuc());
}
IEnumerator waitFuc()
{
//等待动画完成
yield return twn.WaitForCompletion();
//执行几次循环以后
yield return twn.WaitForElapsedLoops(2);
//等待销毁以后
yield return twn.WaitForKill();
//等待运行的多少时间后
yield return twn.WaitForPosition(1.5f);
//等待到重新来的时候
yield return twn.WaitForRewind();
//等待起始化的时候
yield return twn.WaitForStart();
}
}
十一丶路径动画
这点有些难以讲解,推荐看我一开头推荐的老师讲的视频,然后以下是路径动画创建的整个过程:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using System.Linq;
using System;
public class PathAnimationDOTween : MonoBehaviour
{
//创建一个路径编辑器
public Transform[] listTrans;
void Start()
{
var listPosition = listTrans.Select(u => u.position).ToArray();
transform.DOPath(listPosition, 5f,PathType.Linear,PathMode.Full3D,10,Color.red)
.SetOptions(true,AxisConstraint.None,AxisConstraint.Y) //bool 是否为闭口,锁定哪个轴以及哪个 转向
.SetLookAt(new Vector3(0,0,0)); //一直看到0,0,0这个点
//SetLokkAt(0)一直看前方,数值为0到1,0.3是和正前方的角度的夹角
//SetOptions(bool是否是封闭路径,AxisConstrains.锁定哪个轴,AxisContstrains.锁定哪个角度)
}
}
然后把我们创建的八个新方块拖进来List,然后点击运行,会发现已经创建好路径了,接下来你的Cube将按照设置的参数属性等进行移动
学习产出:
以上便是本人当前对DOTween的所有理解,如果你能看到最后说明你耐心是真的NB。
接下来的文章会对学到DOTween进行综合应用,感谢支持。