參考
Unity 動(dòng)畫(huà)一:DOTween簡(jiǎn)單了解
Unity 動(dòng)畫(huà)二:DOTween使用簡(jiǎn)介
官網(wǎng) http://dotween.demigiant.com/documentation.php
Unity Dotween常用方法詳解
Unity插件之DOTween教程
演示效果可以看視頻:https://www.bilibili.com/video/BV1BK411773V?p=23
DOTween源碼解析
一叭首、DOTween的性能優(yōu)勢(shì)
在一個(gè)循環(huán)中處理64000個(gè)通用浮點(diǎn)數(shù):
在循環(huán)中處理4000個(gè)transform
二赶舆、寫(xiě)法
1、通用格式
//將myVector的值在1秒內(nèi)倦青,補(bǔ)間轉(zhuǎn)換到(3,4,8)
DOTween.To(()=> myVector, x=> myVector = x, new Vector3(3,4,8), 1);
//將myFloat的值在1秒內(nèi)瓮床,補(bǔ)間轉(zhuǎn)換到52
DOTween.To(()=> myFloat, x=> myFloat = x, 52, 1);
2.快捷格式
DOTween包括一些已知的Unity對(duì)象的快捷方式,如Transform姨夹,Rigidbody和Material纤垂。 您可以從對(duì)這些對(duì)象的引用直接啟動(dòng)補(bǔ)間(這也將自動(dòng)將對(duì)象本身設(shè)置為補(bǔ)間目標(biāo))
//將transform在1秒內(nèi)移動(dòng)到(2,3,4)的空間位置
transform.DOMove(new Vector3(2,3,4), 1);
//將rigidbody在1秒內(nèi)移動(dòng)到(2,3,4)的空間位置
rigidbody.DOMove(new Vector3(2,3,4), 1);
//將material的Color(顏色值)在1秒內(nèi)漸變到綠色
material.DOColor(Color.green, 1);
無(wú)論您選擇哪種方式,當(dāng)創(chuàng)建一個(gè)補(bǔ)間時(shí)磷账,都會(huì)返回一個(gè)Tweener或一個(gè)Sequence峭沦,可以根據(jù)實(shí)際需要保持這個(gè)引用,供之后使用逃糟。
三吼鱼、控制方式
因?yàn)镈OTween有多種寫(xiě)法和引用,所以控制DOTween的方式也有不少選擇绰咽。以Rewind(回放)功能為例
1菇肃、靜態(tài)調(diào)用:
//回放所有補(bǔ)間
DOTween.RewindAll();
//根據(jù)ID回放相關(guān)補(bǔ)間
DOTween.Rewind(myId);
2、通過(guò)引用
//通過(guò)myTween引用來(lái)回放
myTween.Rewind();
3取募、快捷調(diào)用
//回放transform上所有的補(bǔ)間動(dòng)畫(huà)
transform.DORewind();
4.FORM補(bǔ)間
顧名思義琐谤,F(xiàn)ORM就是“從……來(lái)”的意思,即對(duì)應(yīng)的最終值的部分就是變成了“初始值”玩敏。例如:
//常規(guī)補(bǔ)間To:將transform在1秒內(nèi)斗忌,橫向移動(dòng)到2的位置
transform.DOMoveX(2, 1);
//FROM模式:將transform在1秒內(nèi),從2的位置移動(dòng)到現(xiàn)在的位置
transform.DOMoveX(2, 1).From();
//FROM相對(duì)值模式:將transform在1秒內(nèi)旺聚,從現(xiàn)在橫向+2的位置织阳,移動(dòng)到現(xiàn)在的位置
transform.DOMoveX(2, 1).From(true);
5.鏈?zhǔn)皆O(shè)置SetEase SetLoops SetDelay
DOTween可以通過(guò)Set方法進(jìn)行一系列的補(bǔ)間動(dòng)畫(huà)實(shí)現(xiàn),通過(guò)On來(lái)進(jìn)行回調(diào)砰粹。
//將transform在2秒內(nèi)唧躲,移動(dòng)到(2,2,2)位置,使用OutQuint的減速動(dòng)畫(huà)形式重復(fù)4次碱璃,動(dòng)畫(huà)結(jié)束后調(diào)用myFunction方法
transform.DOMove(new Vector3(2,2,2), 2)
.SetEase(Ease.OutQuint)
.SetLoops(4)
.OnComplete(myFunction);
//相同作用的另外一種寫(xiě)法
Tween myTween = transform.DOMove(new Vector3(2,2,2), 2);
myTween.SetEase(Ease.OutQuint);
myTween.SetLoops(4);
myTween.OnComplete(myFunction);
6.補(bǔ)間的生命周期 SetAutoKill
當(dāng)您創(chuàng)建補(bǔ)間動(dòng)畫(huà)的時(shí)候弄痹,它通常是自動(dòng)播放的,直到完成其所有循環(huán)內(nèi)容后才會(huì)結(jié)束嵌器。但是界酒,您可以更改全局屬性defaultAutoPlay來(lái)控制。
當(dāng)補(bǔ)間動(dòng)畫(huà)播放結(jié)束之后嘴秸,通常是自動(dòng)銷毀的毁欣。但是庇谆,您可以更改全局屬性defaultAutoKill來(lái)控制。如需要重復(fù)使用相同的補(bǔ)間動(dòng)畫(huà)凭疮,只要將autoKill設(shè)置為False便可饭耳,或者可以在設(shè)置補(bǔ)間動(dòng)畫(huà)的時(shí)候SetAutoKill(false)。
如果您沒(méi)用使用安全模式执解,當(dāng)補(bǔ)間動(dòng)畫(huà)實(shí)施的目標(biāo)為空(null)時(shí)寞肖,可能會(huì)發(fā)生錯(cuò)誤。
7.緩存和最大補(bǔ)間數(shù)量
如果您可以激活循環(huán)重用DOTween緩存衰腌,那么您就不必再額外創(chuàng)建新的對(duì)象了新蟆。
一般建議設(shè)置最大Tweener數(shù)量為200,最大Sequence數(shù)量為50右蕊。如果您需要更多功能琼稻,DOTween會(huì)自動(dòng)增加兩個(gè)的數(shù)量。但是饶囚,您可以直接設(shè)置帕翻,如下所示:
// 設(shè)置最大 Tweener數(shù)量為 3000 ,最大Sequence數(shù)量為 200
DOTween.SetTweensCapacity(3000, 200);
當(dāng)要重置DOTween的緩存時(shí)萝风,只需要調(diào)用DOTween.Clear()就可以了嘀掸。
四、Transform拓展方法
1.position
//1)改變世界坐標(biāo)
//移動(dòng)方法规惰,第一個(gè)參數(shù)是要移動(dòng)到的目標(biāo)點(diǎn)睬塌,不是移動(dòng)這個(gè)向量的距離
transform.DOMove(new Vector3(1, 1, 1), 2);
//只控制x軸上的移動(dòng),其他兩個(gè)方向同理
transform.DOMoveX(1, 2);
//2)改變局部坐標(biāo)
transform.DOLocalMove(new Vector3(1, 1, 1), 2);
transform.DOLocalMoveX(1, 2);
2.rotation DOLookAt
//1)世界旋轉(zhuǎn)
//旋轉(zhuǎn)到給定的值歇万,改變的是歐拉角
transform.DORotate(new Vector3(0, 90, 0), 2);
//旋轉(zhuǎn)到給定的值衫仑,改變的是四元數(shù)
transform.DORotateQuaternion(new Quaternion(0.1f, 0.1f, 0.1f, 0.1f), 2);
//2)局部旋轉(zhuǎn)
//旋轉(zhuǎn)到給定的值,改變的是歐拉角
transform.DOLocalRotate(new Vector3(0, 90, 0), 2);
//旋轉(zhuǎn)到給定的值堕花,改變的是四元數(shù)
transform.DOLocalRotateQuaternion(new Quaternion(0.1f, 0.1f, 0.1f, 0.1f), 2);
//在給定時(shí)間內(nèi),平滑的讓自身的z軸正方向指向目標(biāo)點(diǎn)
transform.DOLookAt(new Vector3(0, 0, 0), 2);
第三個(gè)參數(shù)是旋轉(zhuǎn)模式RotateMode mode = RotateMode.Fast
- RotateMode.Fast:DoTween中旋轉(zhuǎn)的默認(rèn)模式粥鞋,若無(wú)顯示的指明旋轉(zhuǎn)模式缘挽,那么此模式為當(dāng)前旋轉(zhuǎn)模式。但是使用此方法旋轉(zhuǎn)呻粹,每次到了360就歸0了壕曼,可以直接將endvalue設(shè)置為370試試,物體只會(huì)旋轉(zhuǎn)10度等浊。
- RotateMode.FastBeyond360:超越360度腮郊,字面意思即可理解。同樣設(shè)置370度筹燕,物體真的會(huì)從當(dāng)前的度數(shù)轧飞,旋轉(zhuǎn)到370度衅鹿,且不會(huì)歸零。
- RotateMode.LocalAxisAdd:先從字面分析过咬,local和上述講的是一樣的大渤,基于自身當(dāng)前旋轉(zhuǎn)度數(shù)(localrotation)。add掸绞,是指在當(dāng)前旋轉(zhuǎn)度數(shù)的基礎(chǔ)上增加endvalue的值泵三。
- RotateMode.WorldAxisAdd:直接分析world,是指相對(duì)于世界的旋轉(zhuǎn)衔掸,若endvalue的值是(0烫幕,0,10)敞映,意思是以世界的z軸為方向较曼,增加10度的旋轉(zhuǎn)量。
3.Scale
//同上面一樣驱显,這里改變物體的縮放到目標(biāo)值
transform.DOScale(new Vector3(2, 2, 2), 2);
//其他兩個(gè)軸向同理
transform.DOScaleX(3, 2);
4.Punch 彈簧沖擊
- 第一個(gè)參數(shù) punch:表示方向及強(qiáng)度
- 第二個(gè)參數(shù) duration:表示動(dòng)畫(huà)持續(xù)時(shí)間
- 第三個(gè)參數(shù) vibrato:震動(dòng)次數(shù)
- 第四個(gè)參數(shù) elascity:
這個(gè)值是0到1的
當(dāng)為0時(shí)诗芜,就是在起始點(diǎn)到目標(biāo)點(diǎn)之間運(yùn)動(dòng)
不為0時(shí),會(huì)把你賦的值乘上一個(gè)參數(shù)埃疫,作為你運(yùn)動(dòng)方向反方向的點(diǎn)伏恐,物體在這個(gè)點(diǎn)和目標(biāo)點(diǎn)之間運(yùn)動(dòng)
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);
5.Shake 抖動(dòng)
- 參數(shù):持續(xù)時(shí)間,力量栓霜,震動(dòng)翠桦,隨機(jī)性,淡出
- 力量:實(shí)際就是震動(dòng)的幅度,可以理解成相機(jī)施加的力的大小 使用Vector3可以選擇每個(gè)軸向不同的強(qiáng)度
- 震動(dòng):震動(dòng)次數(shù)
- 隨機(jī)性:改變震動(dòng)方向的隨機(jī)值(大懈炻:0~180)
- 淡出:就是運(yùn)動(dòng)最后是否緩慢移動(dòng)回到原本位置
transform.DOShakePosition(1, 5, 10, 50, true);
transform.DOShakeRotation(3);
transform.DOShakeScale(3);
6.Blend 混合動(dòng)畫(huà)
原本同時(shí)執(zhí)行兩個(gè)Move方法销凑,只會(huì)執(zhí)行最新的一個(gè)動(dòng)畫(huà)命令例如:
transform.DOMove(Vector3.one, 2);
transform.DOMove(Vector3.one* 2, 2);
結(jié)果是物體運(yùn)動(dòng)到了(2,2,2)坐標(biāo)上
DOBlendableMoveBy方法有兩個(gè)特點(diǎn)
1)允許多個(gè)同時(shí)執(zhí)行
例如:
transform.DOBlendableMoveBy(new Vector3(1, 1, 1), 1);
transform.DOBlendableMoveBy(new Vector3(-1, 0, 0), 1);
假設(shè)起始點(diǎn)為(0,0,0),最后動(dòng)畫(huà)停止時(shí)的坐標(biāo)就是(0,1,1)
2)它是增量動(dòng)畫(huà)
transform.DOBlendableMoveBy(new Vector3(1, 1, 1), 1);
假設(shè)起始點(diǎn)為(1,1,1)仅炊,最后動(dòng)畫(huà)停止時(shí)的坐標(biāo)就是(2,2,2)
它的參數(shù)不是目標(biāo)點(diǎn)斗幼,而是要移動(dòng)的量
以下三個(gè)函數(shù)同理
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
這個(gè)的基礎(chǔ)是物體的Shader中有Main Color這個(gè)屬性的抚垄,沒(méi)有的話不能改變蜕窿,是有解決辦法的
material.DOColor(Color.black, 2);
2.按照shader的屬性名,修改顏色
material.DOColor(Color.clear, "_TintColor", 2);//""中的是顏色的名字
3. 修改alpha值
material.DOFade(0, 2);
//默認(rèn)為_(kāi)Color呆馁,如果沒(méi)有桐经,則需要添寫(xiě)第二個(gè)參數(shù)
material.DOFade(0, "_TintColor", 2);
4. 顏色漸變
//腳本中添加這個(gè)屬性,在UNITY視圖中就能選顏色漸變器
public Gradient _gradient;
Gradient是unity的漸變編輯器(下面有漸變編輯器的圖)
material.DOGradientColor(_gradient, "_Color", 3);
5.改變材質(zhì)offset的值浙滤,改變貼圖的UV坐標(biāo)
material.DOOffset(new Vector2(1, 1), 2);
6.改變提供的shader屬性的名稱對(duì)應(yīng)的Vector4值
material.DOVector(new Vector4(0, 0, 0, 1), "_Color", 3);
7.顏色混合
跟位置混合動(dòng)畫(huà)同理阴挣,可以同時(shí)執(zhí)行而不干擾,產(chǎn)生混合在一起的顏色
material.DOBlendableColor(Color.red, "_Color", 3);
material.DOBlendableColor(Color.yellow, "_Color", 3);
六纺腊、camera的拓展方法
1.調(diào)整屏幕視角的寬高比 第一個(gè)參數(shù)是(寬/高)的比值
Camera camera = GetComponent<Camera>();
camera.DOAspect(0.6f, 2);
2.改變相機(jī)background參數(shù)的顏色
camera.DOColor(Color.red, 2);
3.改變相機(jī)近切面的值
camera.DONearClipPlane(1, 2);
4.改變相機(jī)遠(yuǎn)切面的值
camera.DOFarClipPlane(700, 2);
5.改變相機(jī)FOV的值畔咧,放大鏡效果
camera.DOFieldOfView(30, 2);
6.改變相機(jī)正交大小
camera.DOOrthoSize(10, 2);
7.按照屏幕像素計(jì)算的顯示范圍
camera.DOPixelRect(new Rect(0f, 0f, 800, 500f), 2);
8.按照屏幕百分比計(jì)算的顯示范圍
camera.DORect(new Rect(0.0f, 0.0f, 0.5f, 0.5f), 2);
9.相機(jī)震動(dòng)
相機(jī)震動(dòng)效果 參數(shù):持續(xù)時(shí)間茎芭,力量,震動(dòng)盒卸,隨機(jī)性骗爆,淡出
力量:實(shí)際就是震動(dòng)的幅度,可以理解成相機(jī)施加的力的大小 使用Vector3可以選擇每個(gè)軸向不同的強(qiáng)度
震動(dòng):震動(dòng)次數(shù)
隨機(jī)性:改變震動(dòng)方向的隨機(jī)值(大小:0~180)
淡出:就是運(yùn)動(dòng)最后是否緩慢移動(dòng)回到原本位置
camera.transform.DOShakePosition(1, 10, 10, 50, false);
七蔽介、Text拓展方法 (打字機(jī)效果)
Text text = GetComponent<Text>();
text.DOColor(Color.black, 2);//顏色
text.DOFade(0, 2);//透明度
text.DOBlendableColor(Color.black, 2);//顏色混合
第一個(gè)參數(shù)傳入的內(nèi)容按照時(shí)間摘投,一個(gè)字一個(gè)字的輸入到文本框中
//.SetEase(Ease.Linear)是按勻速打字
text.DOText("context", 2).SetEase(Ease.Linear);
八、Sequence
在實(shí)際的需求中虹蓄,一個(gè)動(dòng)畫(huà)一般都包含對(duì)多個(gè)物體的操作犀呼,那么如何使用DoTween制作這種動(dòng)畫(huà)呢?對(duì)于一些簡(jiǎn)單的動(dòng)畫(huà)薇组,直接順序執(zhí)行多個(gè)DoTween語(yǔ)句即可外臂;對(duì)于一些復(fù)雜的動(dòng)畫(huà),諸如包含延時(shí)律胀、動(dòng)畫(huà)事件回調(diào)宋光、播放音效等的動(dòng)畫(huà),可以利用DoTween的動(dòng)畫(huà)隊(duì)列完成這些操作炭菌。如果你有Cosos等2d引擎的使用經(jīng)驗(yàn)罪佳,那么Sequence你一定不會(huì)陌生。
Sequence quence = DOTween.Sequence();
1.添加動(dòng)畫(huà)到隊(duì)列中
quence.Append(transform.DOMove(-Vector3.one, 2));
2.添加時(shí)間間隔
quence.AppendInterval(1);
3.按時(shí)間點(diǎn)插入動(dòng)畫(huà)
第一個(gè)參數(shù)為時(shí)間點(diǎn)黑低,此方法把動(dòng)畫(huà)插入到規(guī)定的時(shí)間點(diǎn)
以這句話為例赘艳,它把DORotate動(dòng)畫(huà)添加到此隊(duì)列的0秒時(shí)執(zhí)行,雖然它不是最先添加進(jìn)隊(duì)列的
在某時(shí)間點(diǎn)插入克握,和本身隊(duì)列不沖突蕾管,同時(shí)進(jìn)行
quence.Insert(0, transform.DORotate(new Vector3(0, 90, 0), 2));
4.join 加入當(dāng)前動(dòng)畫(huà)
Join會(huì)加入和讓動(dòng)畫(huà)與當(dāng)前正在執(zhí)行的動(dòng)畫(huà)一起執(zhí)行
如下兩行代碼,DOMove會(huì)和DOScale一起執(zhí)行
quence.Append(transform.DOScale(Vector3.one * 5, 2));
quence.Join(transform.DOMove(Vector3.one * 5, 2));
5.預(yù)添加動(dòng)畫(huà)
預(yù)添加 會(huì)直接添加動(dòng)畫(huà)到Append的前面菩暗,也就是最開(kāi)始的時(shí)候
quence.Prepend(transform.DOScale(Vector3.one * 0.5f, 1));
這里需要特別說(shuō)一下預(yù)添加的執(zhí)行順序問(wèn)題
它這里也采取了隊(duì)列的性質(zhì)掰曾,不過(guò),預(yù)添加與原本的的隊(duì)列相比是一個(gè)反向隊(duì)列
例如:
quence.Append(transform.DOMove(Vector3.one, 2));
quence.Prepend(transform.DOMove(-Vector3.one * 2, 2));
quence.PrependInterval(1);
執(zhí)行順序是 PrependInterval----Prepend---- - Append
就是最后添加的會(huì)在隊(duì)列的最頂端
6.預(yù)添加時(shí)間間隔
quence.PrependInterval(1);
7.回調(diào)函數(shù)
//1)預(yù)添加回調(diào)停团,直接添加到最開(kāi)始的時(shí)候
quence.PrependCallback(PreCallBack);
//2)在規(guī)定的時(shí)間點(diǎn)加入回調(diào)
quence.InsertCallback(0, InsertCallBack);
//3)添加回調(diào)
quence.AppendCallback(CallBack);
private void PreCallBack()
{
Debug.Log("PreCallBack");
}
private void InsertCallBack()
{
Debug.Log("InsertCallBack");
}
private void CallBack()
{
Debug.Log("CallBack");
}
AppendCallback 當(dāng)前執(zhí)行的隊(duì)列動(dòng)畫(huà)完成后自動(dòng)調(diào)用
InsertCallbakc 它的執(zhí)行時(shí)間點(diǎn)只跟他填寫(xiě)的時(shí)間參數(shù)有關(guān)
九旷坦、動(dòng)畫(huà)設(shè)置 TweenParams
TweenParams para = new TweenParams();
1.設(shè)置動(dòng)畫(huà)循環(huán)
- 第一個(gè)參數(shù)是循環(huán)次數(shù) - 1代表無(wú)限循環(huán)
- 第二個(gè)參數(shù)是循環(huán)方式
- Restart 重新開(kāi)始
- Yoyo 從起始點(diǎn)運(yùn)動(dòng)到目標(biāo)點(diǎn),再?gòu)哪繕?biāo)點(diǎn)運(yùn)動(dòng)回來(lái)客蹋,這樣循環(huán)
- Incremental 一直向著運(yùn)動(dòng)方向運(yùn)動(dòng)
para.SetLoops(-1, LoopType.Yoyo);
2.設(shè)置參數(shù)
transform.DOMove(Vector3.one, 2).SetAs(para);
3.設(shè)置自動(dòng)殺死動(dòng)畫(huà)
參數(shù):false會(huì)緩存,true會(huì)直接釋放
transform.DOMove(Vector3.one, 1).SetAutoKill(true);
4.from補(bǔ)間孽江,從目標(biāo)點(diǎn)移動(dòng)到當(dāng)前點(diǎn)
transform.DOMove(Vector3.one, 2).From(true);
From參數(shù) isRelative(相對(duì)的):
- 為true讶坯,傳入的就是偏移量,即當(dāng)前坐標(biāo) + 傳入值 = 目標(biāo)值
- 為falese岗屏,傳入的就是目標(biāo)值辆琅,即傳入值 = 目標(biāo)值
5.設(shè)置動(dòng)畫(huà)延時(shí)
transform.DOMove(Vector3.one, 2).SetDelay(1);
6.設(shè)置動(dòng)畫(huà)運(yùn)動(dòng)以速度為基準(zhǔn)
使用SetSpeedBased時(shí)漱办,移動(dòng)方式就變成以速度為基準(zhǔn)
原本表示持續(xù)時(shí)間的第二個(gè)參數(shù),就變成表示速度的參數(shù)婉烟,每秒移動(dòng)的單位數(shù)
transform.DOMove(Vector3.one, 1).SetSpeedBased();
7. 設(shè)置動(dòng)畫(huà)ID
可以調(diào)用緩存的動(dòng)畫(huà)
transform.DOMove(Vector3.one, 2).SetId("Id");
DOTween.Play("Id");
8.設(shè)置是否可回收
為true的話娩井,動(dòng)畫(huà)播放完會(huì)被回收,緩存下來(lái)似袁,為false播完就直接銷毀
transform.DOMove(Vector3.one, 2).SetRecyclable(true);
9.設(shè)置動(dòng)畫(huà)為增量運(yùn)動(dòng)
SetRelative參數(shù) isRelative(相對(duì)的):
- 為true洞辣,傳入的就是偏移量,即當(dāng)前坐標(biāo) + 傳入值 = 目標(biāo)值
- 為falese昙衅,傳入的就是目標(biāo)值扬霜,即傳入值 = 目標(biāo)值
transform.DOMove(Vector3.one, 2).SetRelative(true);
10.設(shè)置動(dòng)畫(huà)的幀函數(shù)
第一個(gè)參數(shù) UpdateType: 選擇使用的幀函數(shù)
- UpdateType.Normal:更新每一幀中更新要求。
- UpdateType.Late:在LateUpdate調(diào)用期間更新每一幀而涉。
- UpdateType.Fixed:使用FixedUpdate調(diào)用進(jìn)行更新著瓶。
- UpdateType.Manual:通過(guò)手動(dòng)DOTween.ManualUpdate調(diào)用進(jìn)行更新。
第二個(gè)參數(shù):為T(mén)RUE啼县,則補(bǔ)間將忽略Unity的Time.timeScale
transform.DOMove(Vector3.one, 2).SetUpdate(UpdateType.Normal, true);
十材原、Ease 運(yùn)動(dòng)曲線的設(shè)置
1. 以Ease枚舉作為參數(shù)
Dotween Ease效果演示地址
http://robertpenner.com/easing/easing_demo.html
//勻速運(yùn)動(dòng)
transform.DOMove(Vector3.one, 2).SetEase(Ease.Linear);
transform.DOMove(Vector3.one, 2).SetEase(Ease.Flash, 3, 0f);
第二個(gè)參數(shù) Amplitude(振幅):實(shí)際就是移動(dòng)次數(shù),起始點(diǎn)移動(dòng)到目標(biāo)算移動(dòng)一次季眷,再移動(dòng)回來(lái)移動(dòng)兩次
第三個(gè)參數(shù) period 值的范圍是 -1~1
- 值 > 0時(shí)余蟹,為活動(dòng)范圍的衰減值,活動(dòng)范圍會(huì)由大變小
- 值 = 0時(shí)瘟裸,就是均勻的在起始坐標(biāo)和目標(biāo)坐標(biāo)之間運(yùn)動(dòng)
- 值 < 0時(shí)客叉,會(huì)施加一個(gè)向目標(biāo)坐標(biāo)的一個(gè)力,活動(dòng)范圍一點(diǎn)點(diǎn)增大话告,最后逼近目標(biāo)點(diǎn)
這兩個(gè)參數(shù)只對(duì)Flash, InFlash, OutFlash, InOutFlash這四種曲線有用兼搏,其他的曲線起作用的就只有Ease枚舉參數(shù)
2.使用AnimationCurve組件當(dāng)作參數(shù)
AnimationCurve 橫軸是時(shí)間, 不過(guò)不是具體的時(shí)間,而是時(shí)間比例
AnimationCurve 縱軸是倍數(shù)沙郭,即(起始點(diǎn)和目標(biāo)點(diǎn)距離)*倍數(shù)
假設(shè)縱軸的值為v佛呻,傳入DOMove的第一個(gè)參數(shù)endValue是e,起始點(diǎn)坐標(biāo)是s
此物體最后動(dòng)畫(huà)結(jié)束時(shí)的實(shí)際坐標(biāo)即為 v * (e - s)+s
transform.DOMove(Vector3.one * 2, 1).SetEase(curve);
3. 以回調(diào)函數(shù)為參數(shù)
transform.DOMove(Vector3.one * 2, 1).SetEase(MyEaseFun);
返回值是運(yùn)動(dòng)距離的百分比 值應(yīng)為0~1之間病线,0為起點(diǎn)吓著,1為終點(diǎn),不然停留的位置不會(huì)是目標(biāo)位置
參數(shù):1、當(dāng)前動(dòng)畫(huà)運(yùn)行的時(shí)間送挑,2醉拓、持續(xù)時(shí)間
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.回調(diào)函數(shù)
1)動(dòng)畫(huà)完成回調(diào)
transform.DOMove(Vector3.one, 2).OnComplete(() => { Debug.Log("完成"); });
2)動(dòng)畫(huà)被殺死時(shí)回調(diào)
transform.DOMove(Vector3.one, 2).OnKill(() => { });
3)動(dòng)畫(huà)播放時(shí)回調(diào),暫停后重新播放也會(huì)調(diào)用
transform.DOMove(Vector3.one, 3).OnPlay(() => { });
4)動(dòng)畫(huà)暫停時(shí)回調(diào)
transform.DOMove(Vector3.one, 2).OnPause(() => { });
5)動(dòng)畫(huà)回退時(shí)回調(diào)
以下情況會(huì)被調(diào)用
使用DORestart重新播放時(shí)
使用Rewind倒播動(dòng)畫(huà)完成時(shí)
使用DOFlip翻轉(zhuǎn)動(dòng)畫(huà)完成時(shí)
使用DOPlayBackwards反向播放動(dòng)畫(huà)完成時(shí)
transform.DOMove(Vector3.one, 2).OnRewind(() => { });
6)只在第一次播放動(dòng)畫(huà)時(shí)調(diào)用,在play之前調(diào)用
transform.DOMove(Vector3.one, 2).OnStart(() => { });
7)完成單個(gè)循環(huán)周期時(shí)觸發(fā)
transform.DOMove(Vector3.one, 2).OnStepComplete(() => { });
8)幀回調(diào)
transform.DOMove(Vector3.one, 2).OnUpdate(() => { });
9)在路徑動(dòng)畫(huà)時(shí)捕虽,改變目標(biāo)點(diǎn)時(shí)的回調(diào)蜜自,參數(shù)為當(dāng)前目標(biāo)點(diǎn)的下標(biāo)
transform.DOMove(Vector3.one, 2).OnWaypointChange((value) => { });
5.動(dòng)畫(huà)控制方法
1)播放
transform.DOPlay();
2)暫停
transform.DOPause();
3)重播
transform.DORestart();
4)倒播,此方法會(huì)直接退回起始點(diǎn)
transform.DORewind();
5)平滑倒播,此方法會(huì)按照之前的運(yùn)動(dòng)方式從當(dāng)前位置退回起始點(diǎn)
transform.DOSmoothRewind();
6)殺死動(dòng)畫(huà)
transform.DOKill();
7)翻轉(zhuǎn)補(bǔ)間的方向欺缘,起始點(diǎn)變目標(biāo)點(diǎn)
transform.DOFlip();
8)跳轉(zhuǎn)時(shí)間點(diǎn)
第一個(gè)參數(shù)跳轉(zhuǎn)的時(shí)間點(diǎn)栋豫,第二個(gè)參數(shù)是跳轉(zhuǎn)后是否播放動(dòng)畫(huà)
transform.DOGoto(1.5f, true);
9)反向播放動(dòng)畫(huà)
反向播放動(dòng)畫(huà),在動(dòng)畫(huà)播放到一半時(shí)執(zhí)行谚殊,會(huì)退回起始點(diǎn)丧鸯,在一開(kāi)始執(zhí)行看不到效果是因?yàn)椋矬w本身就在起始點(diǎn)
transform.DOPlayBackwards();
10)正向播放動(dòng)畫(huà)
transform.DOPlayForward();
11)TogglePause
當(dāng)暫停時(shí)嫩絮,執(zhí)行就繼續(xù)播放丛肢,播放時(shí),執(zhí)行就暫停
transform.DOTogglePause();
6.獲取類方法
1)返回所有暫停的動(dòng)畫(huà)絮记,沒(méi)有則返回null
List<Tween> list = DOTween.PausedTweens();
2)返回所有真正播放的動(dòng)畫(huà)摔踱,沒(méi)有則返回null
List<Tween> list = DOTween.PlayingTweens();
3)獲取給定ID的數(shù)組
返回滿足條件的動(dòng)畫(huà)數(shù)組
第一個(gè)參數(shù)是動(dòng)畫(huà)的ID
第二個(gè)參數(shù)是是否只收集正在播放的動(dòng)畫(huà),因?yàn)镈OTween會(huì)緩存之前播放過(guò)的動(dòng)畫(huà)
List<Tween> list = DOTween.TweensById("id", true);
4)返回給定對(duì)象的數(shù)組
返回滿足條件的動(dòng)畫(huà)數(shù)組
第一個(gè)參數(shù)是播放動(dòng)畫(huà)的對(duì)象
例如:transform.DOMove(Vector3.one, 2); 第一個(gè)參數(shù)就傳入transform
material.DOColor(Color.White, 2); 第一個(gè)參數(shù)就傳入材質(zhì)對(duì)象material
第二個(gè)參數(shù)是是否只收集正在播放的動(dòng)畫(huà)
List<Tween> list = DOTween.TweensByTarget(transform, true);
5)收集傳入的對(duì)象是否有動(dòng)畫(huà)在活動(dòng)
第一個(gè)參數(shù)為檢測(cè)的 (對(duì)象 或 ID)
第二個(gè)參數(shù)為是否檢測(cè)動(dòng)畫(huà)在播放狀態(tài)
為true時(shí)怨愤,給定對(duì)象在播放狀態(tài)時(shí),延時(shí)狀態(tài)也算正在播放 返回true
為false時(shí)派敷,只檢測(cè)給定對(duì)象是否有動(dòng)畫(huà)(在pause狀態(tài)時(shí)也算)有則返回true
List<Tween> list = DOTween.IsTweening(transform,true);
6)正在播放的動(dòng)畫(huà)的總數(shù),目前處于延遲播放狀態(tài)的動(dòng)畫(huà)也算
int num = DOTween.TotalPlayingTweens();
7.獲取實(shí)例方法
Tween _tweener = transform.DOMove(Vector3.one, 1).SetLoops(3);
//1)表示動(dòng)畫(huà)執(zhí)行時(shí)間的屬性撰洗,可讀可寫(xiě)篮愉,是設(shè)置動(dòng)畫(huà)的進(jìn)度
_tweener.fullPosition = 1;//設(shè)置動(dòng)畫(huà)的時(shí)間點(diǎn)為1秒
//2)表示動(dòng)畫(huà)執(zhí)行完的次數(shù)(包括循環(huán)),配合.OnStepComplete(() => { })使用
int num = _tweener.CompletedLoops();
//3)獲取動(dòng)畫(huà)的延遲時(shí)間
float time = _tweener.Delay();
//4)獲取動(dòng)畫(huà)的持續(xù)時(shí)間
//參數(shù)為true 表示計(jì)算循環(huán)的時(shí)間差导,無(wú)限循環(huán)返回Infinity试躏,flase不包括循環(huán)的時(shí)間
float time = _tweener.Duration(false);//flase返回1,true返回3
//5)動(dòng)畫(huà)已播放的時(shí)間
//參數(shù)為true 表示計(jì)算循環(huán)的時(shí)間
float time = _tweener.Elapsed();//false返回0-1设褐,true返回0-3
//6)返回動(dòng)畫(huà)進(jìn)度的百分比
//起始點(diǎn)為0 目標(biāo)點(diǎn)為1 當(dāng)yoyo循環(huán)模式下颠蕴,值會(huì)從0變到1再?gòu)?變到0
float percent = _tweener.ElapsedDirectionalPercentage();
//7)返回動(dòng)畫(huà)區(qū)間已用的百分比
//單次循環(huán)的數(shù)值為0到1
//參數(shù)為 是否包含循環(huán) 為true時(shí) 返回值是循環(huán)總區(qū)間的已用百分比 若為無(wú)限循環(huán) 返回值為0
transform.DOMove(Vector3.one, 1).SetLoops(3) // false時(shí)總里程為1,true時(shí)總里程為3
_tweener.ElapsedPercentage(true);
//8)動(dòng)畫(huà)是否在活動(dòng)
_tweener.IsActive();
//9)是否是反向動(dòng)畫(huà)
_tweener.IsBackwards();
//10)動(dòng)畫(huà)是否完成
_tweener.IsComplete();
//11)是否以初始化
_tweener.IsInitialized();
//12)是否正在播放
_tweener.IsPlaying();
//13)返回循環(huán)次數(shù)助析,無(wú)限循環(huán)為Infinity
_tweener.Loops();
8.協(xié)程方法
private Tweener _tweener;
void Start ()
{
_tweener = transform.DOMove(Vector3.one * 2, 1).SetLoops(3);
StartCoroutine(Wait());
}
private IEnumerator Wait()
{
//1)等待動(dòng)畫(huà)執(zhí)行完
yield return _tweener.WaitForCompletion();
//2)等待指定的循環(huán)次數(shù)
//參數(shù)為執(zhí)行次數(shù)犀被,等待傳入的循環(huán)次數(shù)后,繼續(xù)執(zhí)行
//若是傳入的次數(shù)大于動(dòng)畫(huà)的循環(huán)次數(shù) 則在動(dòng)畫(huà)結(jié)束時(shí)繼續(xù)執(zhí)行
yield return _tweener.WaitForElapsedLoops(2);
//3)等待動(dòng)畫(huà)被殺死
yield return _tweener.WaitForKill();
//4)等待動(dòng)畫(huà)執(zhí)行指定時(shí)間
//參數(shù)為時(shí)間外冀,動(dòng)畫(huà)執(zhí)行傳入的時(shí)間之后或動(dòng)畫(huà)執(zhí)行完畢寡键,繼續(xù)執(zhí)行
yield return _tweener.WaitForPosition(0.5f);
//5)等待動(dòng)畫(huà)回退
//以下情況會(huì)繼續(xù)執(zhí)行函數(shù)
//使用DORestart重新播放時(shí)
//使用Rewind倒播動(dòng)畫(huà)完成時(shí)
//使用DOFlip翻轉(zhuǎn)動(dòng)畫(huà)完成時(shí)
//使用DOPlayBackwards反向播放動(dòng)畫(huà)完成時(shí)
yield return _tweener.WaitForRewind();
//6)等待Start執(zhí)行后繼續(xù)執(zhí)行
yield return _tweener.WaitForStart();
}
十一、路徑動(dòng)畫(huà)
Dotween對(duì)于路徑動(dòng)畫(huà)就只提供了兩個(gè)方法雪隧,一個(gè)是針對(duì)于世界坐標(biāo)的西轩,一個(gè)是針對(duì)于局部坐標(biāo)的,本質(zhì)上沒(méi)啥區(qū)別脑沿,就以世界坐標(biāo)的方法為例藕畔,進(jìn)行講解
- waypoints: 是提供路徑上點(diǎn)的坐標(biāo),需要按順序添加進(jìn)數(shù)組
- duration:路徑動(dòng)畫(huà)的整體持續(xù)時(shí)間
- pathType:路徑類型(就是點(diǎn)于點(diǎn)之間路徑連線的生成方式)
它內(nèi)部預(yù)定義了兩種類型
Linear:直線
CatmullRom:曲線 - pathModel: 路徑模式(用于確定正確的LookAt方向)
它內(nèi)部定義了四種類型
Ignore:忽略此參數(shù)和設(shè)置的LookAt參數(shù)
Full3D:在3d場(chǎng)景下庄拇,代表物體可以看向任何方向
TopDown2D:代表物體只能上下旋轉(zhuǎn)注服,看向物體
Sidescroller2D:代表物體只能左右旋轉(zhuǎn)看向物體 - resolution:路徑分辨率,代表路徑點(diǎn)之間的曲線由多少個(gè)點(diǎn)構(gòu)成,也就是點(diǎn)越多祠汇,曲線就越圓,此參數(shù)在直線路徑類型下無(wú)效
- gizmoColor:在Scene視圖中熄诡,生成的路徑曲線的顏色
public Transform[] PointList;//所有的路徑點(diǎn)
void Start () {
//Transform數(shù)組轉(zhuǎn)換成vector數(shù)組
var positions = PointList.Select(u => u.position).ToArray();
transform.DOPath(positions,5,PathType.CatmullRom,PathMode.Full3D,50,Color.blue);
}
1.SetOptions
- closePath:是否是封閉路徑可很,設(shè)為true的話,會(huì)形成閉環(huán)凰浮,最后運(yùn)動(dòng)回起點(diǎn)
- lockPosition:鎖定位置我抠,參數(shù)為軸向,例如袜茧,填入AxisConstraint.X的話菜拓,橫向的位移將被鎖定,物體只能在其他方向上移動(dòng)
- lockRotation:鎖定旋轉(zhuǎn)笛厦,參數(shù)為軸向纳鼎,和鎖定位置同理,鎖定的軸向不能旋轉(zhuǎn)
2.SetLookAt
這個(gè)方法是很重要的方法裳凸,它的后兩個(gè)參數(shù)贱鄙,是提供看向的軸向,一般很少更改姨谷,就不介紹了逗宁,主要介紹第一個(gè)參數(shù)
它針對(duì)于第一個(gè)參數(shù)的改變,有三種重載
∶蜗妗(1)Transform類型參數(shù) lookAtTransform:也就是要看向的物體
∠箍拧(2)Vector3類型參數(shù) lookAtPosition:也就是要看向的位置
(3)float類型的參數(shù) lookAhead:一個(gè)向路徑的前方看的參數(shù)
前兩個(gè)很容易理解捌议,就不多說(shuō)了哼拔,主要說(shuō)一下第三種 lookAhead
3.lookAhead 參數(shù)
這個(gè)參數(shù)的取值范圍是0到1的
首先說(shuō)明,它值的變化禁灼,產(chǎn)生的效果
這個(gè)值的變化管挟,決定了物體開(kāi)始移動(dòng)時(shí)的朝向。這個(gè)參數(shù)在不同數(shù)值下的效果弄捕,受到SetOptions的第一個(gè)參數(shù)closePath影響僻孝。比較通俗的解釋:
(1)closePath為false (運(yùn)動(dòng)最后,物體的朝向移動(dòng)是路徑的運(yùn)動(dòng)方向的前方)
lookAhead = 0:目標(biāo)會(huì)沿著路徑看向前方
lookAhead != 0:目標(biāo)會(huì)按照參數(shù)守谓,決定開(kāi)始運(yùn)動(dòng)時(shí)的朝向穿铆,但是運(yùn)動(dòng)期間會(huì)勻速轉(zhuǎn)動(dòng)朝向,最后朝向會(huì)轉(zhuǎn)回路徑前方的朝向
(2)closePath為true(開(kāi)始時(shí)確定方向后就不會(huì)變化了)
lookAhead = 0:目標(biāo)會(huì)沿著路徑看向前方
lookAhead >0 && lookAhead <1:一直保持開(kāi)始時(shí)的方向(即如上圖所示)
lookAhead = 1:這個(gè)時(shí)候斋荞,SetLookAt沒(méi)有效果荞雏,即物體不會(huì)改變朝向
這里所說(shuō)的朝向是相對(duì)于運(yùn)動(dòng)路徑的朝向
總結(jié):
- lookAhead 參數(shù)的意思就是 看前看的偏移量
- 假設(shè)整個(gè)路徑normalize. 即開(kāi)始點(diǎn)為0,結(jié)束點(diǎn)為1. 走到路程的一半即為0.5.
- 所以如果lookAhead = 0.5 時(shí), 假設(shè)當(dāng)前Transform行走進(jìn)程到 0.1的位置,則會(huì) LookAt 行走進(jìn)程 0.6的位置.
- 如果closePath=true, 則 lookAtPercent = Mathf.Repeat(movePercent + lookAhead, 1);
- 否則closePath=false, 則 lookAtPercent = Mathf.Clamp01(movePercent + lookAhead);
十二、DoTweenPath
下面是一些復(fù)雜屬性的解釋
1.Loops
Loops:循環(huán)次數(shù),動(dòng)畫(huà)循環(huán)播放的次數(shù)
- -1:表示 一直循環(huán)
- 0:表示只播放一次
- 當(dāng)該值>1時(shí)凤优,檢視面板出現(xiàn)LoopType悦陋,顧名思義就是指循環(huán)類型:
- Restart:重新開(kāi)始,后面的動(dòng)畫(huà)循環(huán)播放會(huì)從起點(diǎn)重新開(kāi)始筑辨;
- Yoyo:來(lái)回播放
- Incremental:增加的俺驶,后面的path移動(dòng)動(dòng)畫(huà)會(huì)在上一次循環(huán)的終點(diǎn)的基礎(chǔ)上進(jìn)行播放
2.ID
可以設(shè)置成一個(gè)統(tǒng)一的ID,然后統(tǒng)一KILL掉
public readonly string TweenID_Game = "Game";//所有游戲dotweenID
...
DOTween.Kill(Constant.tweenID.TweenID_Game);
參考使用DOTweenPath中的ID進(jìn)行調(diào)取執(zhí)行DOTweenPath
可以遍歷物體上面所有的DOTweenPath棍辕,通過(guò)ID找到自己想要的那一個(gè)暮现。
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);
是一樣的
第一個(gè)參數(shù) UpdateType: 選擇使用的幀函數(shù)
- UpdateType.Normal:更新每一幀中更新要求。
- UpdateType.Late:在LateUpdate調(diào)用期間更新每一幀楚昭。
- UpdateType.Fixed:使用FixedUpdate調(diào)用進(jìn)行更新栖袋。
- UpdateType.Manual:通過(guò)手動(dòng)DOTween.ManualUpdate調(diào)用進(jìn)行更新。
3.Path Tween Options
- Linear:線型的
- Catmull Rom:曲線
- Close Path:封閉曲線抚太,將起點(diǎn)和終點(diǎn)相連
- Lock Rotation:鎖旋轉(zhuǎn)塘幅,xyzw
Path Mode參見(jiàn)上面的第十一、路徑動(dòng)畫(huà)
- Ignore:忽略此參數(shù)和設(shè)置的LookAt參數(shù)
- Full3D:在3d場(chǎng)景下尿贫,代表物體可以看向任何方向
- TopDown2D:代表物體只能上下旋轉(zhuǎn)晌块,看向物體
- Sidescroller2D:代表物體只能左右旋轉(zhuǎn)看向物體
4.Events:
- OnStart:開(kāi)始時(shí)
- OnPlay:播放時(shí)
- OnUpdate:更新時(shí)
- OnStep:?jiǎn)尾酵瓿蓵r(shí)
- OnComplete:完成時(shí)
- OnCreated:動(dòng)畫(huà)創(chuàng)建時(shí)
事件順序?yàn)椋篛nCreated->OnStart->OnPlay->OnUpdate(一直執(zhí)行,直到完成)帅霜,動(dòng)畫(huà)過(guò)程中單步完成時(shí)執(zhí)行OnStep匆背,整個(gè)動(dòng)畫(huà)完成后執(zhí)行OnComplete。
5.WayPoints:移動(dòng)軌跡點(diǎn)
按住SHIFT+CTRL身冀,然后在場(chǎng)景中點(diǎn)擊钝尸,即可添加路點(diǎn)。同理搂根,SHIFT+ALT則是刪除路點(diǎn)珍促。
其中右邊的Copy to clipboard,將坐標(biāo)復(fù)制至剪貼板剩愧。
6.動(dòng)態(tài)路徑
Unity3d使用DOTween實(shí)現(xiàn)動(dòng)態(tài)路徑方法DOPath和DOTweenPath無(wú)效情況
有個(gè)項(xiàng)目有如題的需求猪叙,主要是能給對(duì)象動(dòng)態(tài)的設(shè)定路徑,并執(zhí)行延路徑運(yùn)動(dòng)的動(dòng)畫(huà)仁卷。路徑上的點(diǎn)是動(dòng)態(tài)生成的穴翩,而且路徑可能不唯一。
總結(jié)
DOPath可以直接設(shè)置路徑點(diǎn)和動(dòng)畫(huà)時(shí)間锦积,實(shí)現(xiàn)執(zhí)行動(dòng)態(tài)路徑的動(dòng)畫(huà)芒帕。
DOTweenPath不知道可不可行,目前測(cè)出的暫時(shí)沒(méi)成功丰介。