參考
Unity動(dòng)畫系統(tǒng)詳解7:Layer是什么凌唬?
學(xué)習(xí)筆記 --- Unity動(dòng)畫系統(tǒng)
“大智岖寞,我的Animator狀態(tài)機(jī)里面的狀態(tài)很多胧奔,現(xiàn)在太難管理了妻枕。我有很多姿勢(shì),比如不拿槍芋齿,拿手槍才沧,拿沖鋒槍,拿步槍集歇,每種姿勢(shì)都要做一個(gè)混合樹桶略,現(xiàn)在再去加蹲的狀態(tài),簡直爆炸诲宇,有沒有什么好辦法际歼?”
“那你想想這些動(dòng)畫之間有沒有什么相似的地方可以提取出來的?”
“要說相似的話姑蓝,它們腿部的動(dòng)畫是類似的鹅心,不管拿槍姿勢(shì)如何,腿部都是一樣的纺荧,只有胳膊的動(dòng)畫不太一樣旭愧。”
“嗯宙暇,這你就算說到點(diǎn)子上了输枯!這時(shí)候可以用下Animator Controller中的Layer
有了Layer,我感覺我的動(dòng)畫可以分為上半身和下半身兩個(gè)Layer占贫,這樣一來就不需要對(duì)每個(gè)拿槍的動(dòng)作設(shè)置移動(dòng)的混合樹了桃熄,應(yīng)該能簡化不少工作“薪#”
“確實(shí)是這樣铃绒,合理利用Layer不僅可以減少動(dòng)畫師的動(dòng)畫制作工作量暴浦,還能在性能上對(duì)游戲進(jìn)行優(yōu)化【保”
使用Layer可以用來管理角色的不同身體部位收夸。比如下半身用于行走或跑步坑匠,上半身用于射擊或投擲物體。
使用動(dòng)畫分層的應(yīng)用主要是以下情況
- 人物動(dòng)畫狀態(tài)涉及分部并行邏輯卧惜,例如槍戰(zhàn)游戲厘灼,腿部動(dòng)作由鍵盤控制夹纫,而上半身動(dòng)作需要由鼠標(biāo)控制進(jìn)行IK瞄準(zhǔn),以及武器切換
- 存在狀態(tài)的融合/疊加效果设凹,例如在正常走動(dòng)的基礎(chǔ)上舰讹,搬運(yùn)物品時(shí),上半身需要持握物品并進(jìn)行IK綁定闪朱,下半身仍是正常走動(dòng)
- 動(dòng)作游戲中月匣,為減輕動(dòng)畫師工作量,取用不同動(dòng)作的部分進(jìn)行組合
一奋姿、Layer
1.管理Layer
點(diǎn)擊加號(hào)可以添加一個(gè)Layer锄开。點(diǎn)擊Layer旁邊的齒輪圖標(biāo),會(huì)彈出一個(gè)小窗口称诗,可以設(shè)置該Layer對(duì)應(yīng)的參數(shù)萍悴。
- Weight 這一層的權(quán)重,0代表該層權(quán)重是0(該層不生效)寓免,1代表該層權(quán)重為1(該層中的動(dòng)畫能完全表現(xiàn))癣诱。混合權(quán)重值可以通過代碼進(jìn)行動(dòng)態(tài)獲取袜香、修改狡刘,例如我們根據(jù)人物的HP值,逐漸將正常走動(dòng)效果困鸥,轉(zhuǎn)為受傷的走動(dòng)效果
animator.GetLayerWeight(layerIndex);
animator.SetLayerWeight(layerIndex, weight);
- Mask 設(shè)置該Layer能控制身體的哪部分嗅蔬,設(shè)置后該Layer上面會(huì)顯示一個(gè)M的小圖標(biāo)。詳細(xì)筆記見下方
- Blending 和其他層混合的模式疾就。
- Override 覆蓋上面的層中對(duì)應(yīng)Mask的部位
- Additive 會(huì)加在之前Layer的動(dòng)畫之上澜术。
- Sync 復(fù)用其他層中的狀態(tài)機(jī)。詳細(xì)筆記見下方
- IK Pass 什么是IK猬腰?得問問大智
二鸟废、Avatar Mask
Avatar Mask,替身遮罩體姑荷,可以作為一種資源文件在Assert目錄下創(chuàng)建
用來設(shè)置該Layer的動(dòng)畫會(huì)影響角色的哪一部分的遮罩盒延。AvatarMask有兩種定義身體遮罩的方式:
- 通過Humanoid身體映射圖
- 通過Transform層次結(jié)構(gòu)選擇包含或不包含的骨骼
1.Humanoid
如果你的動(dòng)畫是人形動(dòng)畫,建議用這一種方式可以快速設(shè)置AvatarMask鼠冕。
身體映射圖包含以下幾部分:
- 頭部
- 左臂
- 右臂
- 左手
- 右手
- 左腿
- 右腿
- Root(腳下的圓形陰影部分)
可以通過鼠標(biāo)點(diǎn)擊每一部分添寺,綠色代表動(dòng)畫可以影響這一部分,紅色代表動(dòng)畫不會(huì)影響懈费。在空白處點(diǎn)擊可以全選/全不選计露。手部和腳部的IK可以開關(guān),表示該部分的IK曲線是否參與動(dòng)畫混合。IK又出現(xiàn)了票罐,一會(huì)去問問大智
2.Transform
如果動(dòng)畫沒有使用Humanoid叉趣,或者你想更精細(xì)的控制遮罩,你可以通過Transform層級(jí)結(jié)構(gòu)來控制每一個(gè)骨骼该押。
- 選擇一個(gè)Avatar(動(dòng)畫模型的Avatar)
- 點(diǎn)擊Import Skeleton按鈕疗杉。avatar的層級(jí)結(jié)構(gòu)會(huì)顯示出來。
- 可以設(shè)置對(duì)應(yīng)的骨骼是否受動(dòng)畫控制
3.Animation頁簽中設(shè)置Mask
在模型導(dǎo)入設(shè)置的Animation頁簽中蚕礼,也可以設(shè)置Mask乡数,設(shè)置后只會(huì)導(dǎo)入對(duì)應(yīng)Mask的動(dòng)畫數(shù)據(jù)。
在這設(shè)置Mask的好處是:可以減少內(nèi)存占用和CPU占用闻牡。因?yàn)椴恍枰纳眢w部位的動(dòng)畫曲線不會(huì)被加載净赴,并且不會(huì)參與計(jì)算。
三罩润、混合示例一
我們需要實(shí)現(xiàn)這樣的一個(gè)效果玖翅,人物能夠進(jìn)行正常的奔跑站立,只不過在我們摁下空格的時(shí)候割以,無論何種姿態(tài)金度,我們都希望人物能夠揮舞自己的右手,而其它姿態(tài)保持原狀態(tài)
1.Base Layer
2.New Layer
在下層實(shí)現(xiàn)一個(gè)從空狀態(tài)(不引用動(dòng)畫切片)严沥,到Wave動(dòng)作的過渡猜极,配置層遮罩限定右手,混合模式為Overrid絕對(duì)坐標(biāo)重寫
3.運(yùn)行
運(yùn)行動(dòng)畫消玄,下層空狀態(tài)時(shí)不對(duì)上層產(chǎn)生影響跟伏。當(dāng)下層過渡為Wave揮手動(dòng)作時(shí),由于層遮罩的配置翩瓜,只重寫右手部分的動(dòng)作受扳,因此人物右手產(chǎn)生揮手動(dòng)作,其它部位仍保持Base Layer的效果兔跌。
四勘高、混合示例二
我們需要在人物原有的正常站立奔跑動(dòng)作上疊加一層擺臂效果(或者其它什么效果)
1.BaseLayer和之前一樣,實(shí)現(xiàn)人物的走動(dòng)和奔跑
2.下層動(dòng)畫使用Addicted疊加模式坟桅,這里我們不使用層Mask华望,而是用ClipMask實(shí)現(xiàn)
3.運(yùn)行效果
當(dāng)下層為擺臂動(dòng)作時(shí),由于ClipMask的配置仅乓,僅雙臂部分的動(dòng)作被疊加到了上層赖舟。這個(gè)擺臂的動(dòng)作其實(shí)是從正常的跑步動(dòng)畫中得到的,但由于ClipMask的配置方灾,僅雙臂部分保留了跑動(dòng)的擺臂動(dòng)作建蹄,其它未激活節(jié)點(diǎn)被恒置于Default狀態(tài)。
在進(jìn)行Addicted裕偿,相對(duì)運(yùn)動(dòng)疊加混合時(shí)洞慎,雙臂部分保留的動(dòng)作就被疊加了上去,而其它部分由于恒置于Default狀態(tài)沒有相對(duì)運(yùn)動(dòng)嘿棘,就不會(huì)產(chǎn)生影響劲腿。
這里其實(shí)通過層Mask配置,而不使用ClipMask鸟妙,也可以實(shí)現(xiàn)焦人,并且有些人也是這么去做的。注意V馗浮;ㄍ帧!這兩種做法其實(shí)都沒有問題房午,針對(duì)這個(gè)簡例也沒有孰優(yōu)孰劣之分矿辽。但我這里就是要借故去提一下ClipMask,去用一下這種做法郭厌,告訴你ClipMask可以這樣用袋倔,以免參與到一些網(wǎng)課老師以及博主的,冷落ClipMask的隊(duì)伍中去折柠。
五宾娜、Sync 復(fù)用其他層中的狀態(tài)機(jī)
有時(shí)能夠在不同的Layer重用其他Layer的狀態(tài)機(jī)非常有用。比如你想模擬一個(gè)“受傷”的狀態(tài)扇售,你有受傷狀態(tài)的各種動(dòng)畫比如走跑跳前塔。這時(shí)候你可以選中Sync復(fù)選框,選擇你想要同步的Layer承冰。狀態(tài)機(jī)的結(jié)構(gòu)會(huì)保持一致嘱根,但是可以設(shè)置不同的Animation Clip。選中時(shí)巷懈,Layer旁邊會(huì)有一個(gè)S小圖標(biāo)该抒。
這意味著,同步出來的Layer不需要再去定義狀態(tài)機(jī)顶燕,并且源Layer中狀態(tài)機(jī)的任何變化都會(huì)同步到這一同步Layer凑保。唯一需要你做的就是設(shè)置每個(gè)State中使用的動(dòng)畫。
Sync復(fù)選框旁邊還有一個(gè)Timing復(fù)選框涌攻。
- 不選中時(shí)欧引,Sync出來的Layer中每一個(gè)State的動(dòng)畫長度會(huì)變?yōu)樵碙ayer中的時(shí)長。
- 選中時(shí)恳谎,根據(jù)Weight調(diào)整動(dòng)畫時(shí)長芝此,Weight為1時(shí)使用Sync Layer中的動(dòng)畫時(shí)長憋肖。
鏡像層與源層的狀態(tài),動(dòng)畫組婚苹,過渡設(shè)置是被綁定在一起的岸更,修改一方會(huì)同時(shí)影響另一方。在游戲運(yùn)行時(shí)膊升,鏡像層會(huì)與源層保持狀態(tài)的同步(按照其中一方Clip的時(shí)間為標(biāo)注怎炊,對(duì)另一方的時(shí)間進(jìn)行控制)。但不同的是廓译,鏡像層可以在動(dòng)畫狀態(tài)中评肆,引用與源層不同的動(dòng)畫片段。從而我們可以通過鏡像層非区,對(duì)一些同步執(zhí)行瓜挽,動(dòng)作不一,可復(fù)用狀態(tài)配置的分層動(dòng)作可以通過鏡像層進(jìn)行快速的創(chuàng)建征绸。例如對(duì)之前的揮手效果秸抚,我們創(chuàng)建一個(gè)鏡像層,引用揮舞另一只手的動(dòng)畫片段歹垫。
六剥汤、IK
參考
Unity動(dòng)畫系統(tǒng)詳解8:IK是什么?
學(xué)習(xí)筆記---3dMax動(dòng)畫系統(tǒng)(機(jī)械排惨、角色動(dòng)畫篇)
1.概念
大智吭敢,我看完了,這個(gè)東西還是很強(qiáng)大的呀暮芭,正好符合我的需要鹿驼。不過這里面有好多地方提到了IK,這個(gè)IK是什么東西呢辕宏?”
“IK是Inverse Kinematics的縮寫畜晰,也就是反向動(dòng)力學(xué)∪鹂穑”
“那是不是還有正向動(dòng)力學(xué)凄鼻?”
“沒錯(cuò),你都會(huì)舉一反三了聚假!大多數(shù)動(dòng)畫是通過旋轉(zhuǎn)骨骼來實(shí)現(xiàn)的块蚌。子骨骼的位置跟著父骨骼的旋轉(zhuǎn)而改變,因此關(guān)節(jié)鏈的終點(diǎn)可以根據(jù)前面的各個(gè)骨骼的角度和相對(duì)位置確定膘格。這種構(gòu)成骨骼動(dòng)畫的方法稱為正向動(dòng)力學(xué)峭范。”
“那反向動(dòng)力學(xué)是不是就是根據(jù)骨骼的最終節(jié)點(diǎn)瘪贱,反向推算之前的骨骼節(jié)點(diǎn)的位置纱控?”
“喲辆毡,不錯(cuò)哦,有長進(jìn)甜害。正如你所說的一樣舶掖。有些時(shí)候我們需要根據(jù)空間中的位置來確定骨骼節(jié)點(diǎn)的位置,比如讓角色拿槍唾那,不同的槍可能握持的位置不太相同访锻,就需要根據(jù)握持的位置來決定角色手的位置褪尝。Unity中的IK支持所有人形動(dòng)畫闹获。”
其他的用途其實(shí)還有比如:角色的頭的旋轉(zhuǎn)河哑,這樣可以和你視角的方向一致避诽。角色的腳的位置,這樣可以讓角色踩在地面更貼合璃谨∩陈”Unity中IK能設(shè)置的部位就是5個(gè),分別是:頭佳吞、左右手拱雏、左右腳。所以沒有其他部位的IK了底扳,我們常見的其實(shí)也都是這些铸抑。
“這樣說我就有些明白了,Animator中的State設(shè)置中的Foot IK是不是就是設(shè)置腳部受IK的影響衷模?”
“是的鹊汛。”
“那Layer中的IK Pass是什么意思呢阱冶?”
“選中IK Pass的時(shí)候刁憋,每幀會(huì)調(diào)用腳本中的OnAnimatorIK方法,可以在這個(gè)方法中動(dòng)態(tài)設(shè)置IK木蹬。
2.如果對(duì)反向動(dòng)力學(xué)還是不太理解至耻,可以參考Inverse Kinematics 逆向運(yùn)動(dòng)學(xué)
逆向動(dòng)力學(xué)的過程在一些場(chǎng)景下十分有用,例如一個(gè)機(jī)械臂镊叁,你需要它去抓取一個(gè)放置在特定的空間位置的物體有梆,那么就需要利用逆向動(dòng)力學(xué)去計(jì)算出機(jī)械臂各個(gè)關(guān)節(jié)的旋轉(zhuǎn)角度,進(jìn)而驅(qū)動(dòng)機(jī)械臂去抓取物體意系。此外泥耀,在游戲編程以及CG動(dòng)畫制作等領(lǐng)域,逆向運(yùn)動(dòng)學(xué)也扮演這非常重要的角色蛔添。
為了使得以上的描述更加形象痰催,這里舉一個(gè)2D逆向運(yùn)動(dòng)學(xué)的例子:
給定兩段長度固定的剛性關(guān)節(jié)兜辞,并固定住了一個(gè)關(guān)節(jié)作為起點(diǎn),最后給出一個(gè)固定的目標(biāo)位置(target)夸溶。此時(shí)只能對(duì)兩個(gè)關(guān)節(jié)進(jìn)行任意角度的旋轉(zhuǎn)逸吵,來讓關(guān)節(jié)的末端達(dá)到給定的目標(biāo)位置,下面的圖例中給出了無解缝裁,唯一解扫皱,兩個(gè)解的情形。
但是鸭叙,某些解決方案將比其他解決方案更好觉啊。 例如,若結(jié)構(gòu)代表一個(gè)動(dòng)畫人物的手臂沈贝,則某些解看起來會(huì)更舒適和自然杠人,而另一些解則會(huì)顯得僵硬及不合理。 所以通常會(huì)有一個(gè)最佳解決方案缀程。
3.設(shè)置頭部IK
“那Layer中的IK Pass是什么意思呢搜吧?”
“選中IK Pass的時(shí)候,每幀會(huì)調(diào)用腳本中的OnAnimatorIK方法杨凑,可以在這個(gè)方法中動(dòng)態(tài)設(shè)置IK
大智:“我們先來看看如何設(shè)置人物的頭部根據(jù)視角旋轉(zhuǎn)滤奈。需要用到這兩個(gè)API:
public void SetLookAtPosition(Vector3 lookAtPosition);
“這個(gè)方法用來設(shè)置頭部看向的位置,比如看向你左邊的窗戶撩满,頭就會(huì)相應(yīng)的旋轉(zhuǎn)蜒程。”
“這個(gè)看起來很簡單嘛伺帘≌烟桑”
“對(duì),這個(gè)方法確實(shí)很簡單伪嫁,不過還有另外一個(gè):”
public void SetLookAtWeight(float weight, float bodyWeight = 0.0f,
float headWeight = 1.0f, float eyesWeight = 0.0f, float clampWeight = 0.5f);
“這個(gè)方法用來設(shè)置IK的權(quán)重领炫,這個(gè)IK會(huì)和原來的動(dòng)畫進(jìn)行混合。如果權(quán)重為1张咳,則完全用IK的位置旋轉(zhuǎn)帝洪;如果權(quán)重為0似舵,則完全用原來動(dòng)畫中的位置和旋轉(zhuǎn)。至少要設(shè)置第一個(gè)參數(shù)葱峡,后面的幾個(gè)參數(shù)都有默認(rèn)值砚哗,但是你也要了解所有參數(shù)的含義:”
- Weight 全局權(quán)重,后面所有參數(shù)的系數(shù)
- bodyWeight 身體權(quán)重砰奕,身體參與LookAt的程度蛛芥,一般是0
- headWeight 頭部權(quán)重,頭部參與LookAt的權(quán)重军援,一般是1
- eyesWeight 眼睛權(quán)重仅淑,眼睛參與LookAt的權(quán)重,一般是0(一般沒有眼睛部分的骨骼)
- clampWeight 權(quán)重的限制盖溺。0代表沒有限制(脖子可能看起來和斷了一樣)漓糙,1代表完全限制(頭幾乎不會(huì)動(dòng)铣缠,像是固定住了)烘嘱。0.5代表可能范圍的一半(180度)。
大智:“有了這兩個(gè)方法你就可以實(shí)現(xiàn)頭部的IK了蝗蛙,不過還有兩點(diǎn)需要注意:”
- 需要勾選對(duì)應(yīng)Layer的IK Pass選項(xiàng)(在Layer的設(shè)置里)蝇庭。
- 代碼需要寫在OnAnimatorIK這個(gè)事件方法里面。
void OnAnimatorIK(int layerIndex)
{
_animator.SetLookAtPosition(pos);
_animator.SetLookAtWeight(1);
}
上面的代碼就是人物的頭部看向一個(gè)位置的代碼捡硅。需要注意的是這個(gè)OnAnimatorIK方法有一個(gè)參數(shù)layerIndex哮内,這個(gè)就是對(duì)應(yīng)的Layer的序號(hào),只有勾選了IK Pass的layer才會(huì)調(diào)用到這個(gè)方法里壮韭,每個(gè)勾選了IK Pass的layer調(diào)用一次北发。
小新:“這樣我就能實(shí)現(xiàn)人物的頭跟著視角移動(dòng)了,哦也”
大智:“是的哦”
4.設(shè)置手腳IK
小新:“那手腳的IK是不是也跟這個(gè)類似的喷屋?”
大智:“是的琳拨,手腳的IK是和這個(gè)類似的,不過API有些不一樣屯曹,我們來看看”
public void SetIKPosition(AvatarIKGoal goal, Vector3 goalPosition);
public void SetIKRotation(AvatarIKGoal goal, Quaternion goalRotation);
設(shè)置頭部時(shí)狱庇,因?yàn)轭^不會(huì)移動(dòng),所以只需要設(shè)置LookAt的位置恶耽,頭部跟隨旋轉(zhuǎn)即可密任。
但是對(duì)于手和腳,需要同時(shí)設(shè)置位置和旋轉(zhuǎn)偷俭。
goal AvatarIKGoal枚舉類型浪讳,包含:
- LeftFoot 左腳
- RightFoot 右腳
- LeftHand 左手
- RightHand 右手
goalPosition/goalRotation IK目標(biāo)位置/旋轉(zhuǎn)
同樣還有設(shè)置權(quán)重的API:
public void SetIKPositionWeight(AvatarIKGoal goal, float value);
public void SetIKRotationWeight(AvatarIKGoal goal, float value);
goal AvatarIKGoal枚舉類型
value IK的權(quán)重,1代表完全使用IK值涌萤,0代表使用原動(dòng)畫的值
常見的設(shè)置手部IK的代碼是(一般需要4行代碼設(shè)置一個(gè)部位):
void OnAnimatorIK(int layerIndex)
{
_animator.SetIKPosition(AvatarIKGoal.LeftHand, position);
_animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
_animator.SetIKRotation(AvatarIKGoal.LeftHand, rotation);
_animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
}
人物左手與球體的綁定示例:
public Transform IKBall_1;//綁定目標(biāo)
public Vector3 IKMove_1;//偏移量
private void OnAnimatorIK(int layerIndex)
{
if (layerIndex == 0)
{
if (animator.GetCurrentAnimatorStateInfo(0).shortNameHash == idleHash)
{
animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
animator.SetIKPosition(AvatarIKGoal.LeftHand,IKBall_1.position +
transform.forward * IKMove_1.z + transform.right * IKMove_1.x + transform.up * IKMove_1.y);
animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
animator.SetIKRotation(AvatarIKGoal.LeftHand,
Quaternion.LookRotation(transform.forward, -transform.right));
}
}
}
5.IK位置/旋轉(zhuǎn)調(diào)節(jié)小技巧
小新:“大智合呐,這個(gè)IK的位置好難調(diào)整啊暮的,我想讓角色拿槍的手能夠貼合這個(gè)槍,有沒有什么簡單的辦法淌实?我這調(diào)了一個(gè)多小時(shí)了冻辩,還不是特別完美拆祈。恨闪。》呕担”
大智:“調(diào)IK是個(gè)慢活咙咽,不過呢,確實(shí)有一些小技巧在里面淤年。IK相關(guān)的代碼涉及到位置和旋轉(zhuǎn)钧敞,這時(shí)候不要傻傻的直接定義一個(gè)位置和旋轉(zhuǎn)來手動(dòng)設(shè)置,最好的辦法是設(shè)置兩個(gè)參照物麸粮,作為IK的位置和旋轉(zhuǎn)的參考溉苛,這樣只需要調(diào)這兩個(gè)參照物就可以了∨澹”
小新:“對(duì)對(duì)對(duì)愚战,這樣的話就不用去修改位置和旋轉(zhuǎn)的值,而是直接修改這倆參照物的位置和旋轉(zhuǎn)就可以了齐遵。我來試一下寂玲。”
小新:“太棒了梗摇,這樣我就能在運(yùn)行時(shí)調(diào)整這個(gè)參考位置拓哟,調(diào)到一個(gè)完美的位置和角度×裘溃”
小新三下五除二彰檬,就調(diào)到了一個(gè)合適的位置和角度。
“調(diào)好了谎砾!”小新高興地喊道逢倍,隨即退出了Play狀態(tài)。
大智:“高興早了吧景图?你這么就退出來了较雕,修改的能保存下來么?” 記好了,點(diǎn)擊Transform組件右上角的小圖標(biāo)亮蒋,可以Copy Component扣典,在運(yùn)行時(shí)點(diǎn)擊,退出運(yùn)行后慎玖,再點(diǎn)擊小圖標(biāo)贮尖,選擇Paste Component Values,這樣就可以將數(shù)據(jù)粘貼回來了趁怔∈酰”
6.關(guān)節(jié)綁定
關(guān)節(jié)綁定是在使用四肢綁定,產(chǎn)生了人物手/腳部對(duì)目標(biāo)位置綁定的基礎(chǔ)上润努,對(duì)人物的肘關(guān)節(jié)/膝關(guān)節(jié)進(jìn)行位置綁定关斜。注意!F探健痢畜!必須在使用了對(duì)應(yīng)的四肢綁定,才能令關(guān)節(jié)綁定生效鳍侣,不能單獨(dú)進(jìn)行關(guān)節(jié)綁定(必須綁定了左手位置丁稀,才能對(duì)左臂肘關(guān)節(jié)進(jìn)行綁定)
關(guān)節(jié)綁定的方法:
animator.SetIKHintPositionWeight(AvatarIKHint, Weight);
animator.SetIKHintPosition(AvatarIKHint, Position);
其中AvatarIKHint是一個(gè)枚舉類型,包括人物的左右肘關(guān)節(jié)拱她,左右膝關(guān)節(jié)
通常我們會(huì)根據(jù)四肢綁定的目標(biāo)位置二驰,結(jié)合人物的Transform物體坐標(biāo)扔罪,按一定的算法/偏移量去推算關(guān)節(jié)綁定的位置秉沼。例如下面的示例代碼,讓人物踩在圓球上并保證小腿豎直:
public Transform IKBall_1;//目標(biāo)球體
public Vector3 IKMove_1;//右腳綁定偏移量
public float kneeMove;//膝關(guān)節(jié)偏移量
private void OnAnimatorIK(int layerIndex)
{
if (layerIndex == 0)
{
if (animator.GetCurrentAnimatorStateInfo(0).shortNameHash == idleHash)
{
animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
animator.SetIKPosition(AvatarIKGoal.RightFoot, IKBall_1.position +
transform.forward * IKMove_1.z + transform.right * IKMove_1.x + transform.up * IKMove_1.y);
animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1);
animator.SetIKRotation(AvatarIKGoal.RightFoot, Quaternion.LookRotation(transform.forward, Vector3.up));
animator.SetIKHintPositionWeight(AvatarIKHint.RightKnee, 1);
animator.SetIKHintPosition(AvatarIKHint.RightKnee, IKBall_1.position +
transform.up * (IKMove_1.y + kneeMove) + transform.forward * IKMove_1.z + transform.right * IKMove_1.x);
}
}
}
7.IK的相互影響
如果IK方法與方法之間會(huì)產(chǎn)生相互影響矿酵,那么它們不能被置于同一個(gè)層中唬复。
相互影響是指一方的IK綁定,會(huì)導(dǎo)致另一方需要綁定的位置有所改變全肮。這是由于進(jìn)行IK綁定的瞬間敞咧,IK效果并不會(huì)立即被體現(xiàn)出來,導(dǎo)致一方對(duì)另一方綁定位置的影響具有滯后性辜腺,導(dǎo)致后綁定的一方綁定位置出錯(cuò)休建。
如果你分別啟用兩端IK綁定,效果無誤评疗,而在同一層中同時(shí)啟用時(shí)出錯(cuò)测砂,那么就可以斷定是相互影響的滯后性導(dǎo)致的。此時(shí)我們可以創(chuàng)建一個(gè)空的動(dòng)畫層并勾選IK Pass用于運(yùn)行IK邏輯百匆,在OnAnimatorIK中使用邏輯分支在不同的層中運(yùn)行兩段邏輯砌些。
例如人物的注視+手部綁定,由于綁定位置是頭部下方的一個(gè)節(jié)點(diǎn),導(dǎo)致同時(shí)啟用時(shí)出錯(cuò)
此時(shí)我們可以創(chuàng)建一個(gè)空層開啟IKPass存璃,并在Animator中對(duì)不同的分層分別使用兩端綁定邏輯
if (animator.GetCurrentAnimatorStateInfo(0).shortNameHash == idleHash)
{
if (layerIndex == 0)
{
//注視綁定
animator.SetLookAtWeight(1, 1, 1, 1, 1);
animator.SetLookAtPosition(Aim.position);
}
else if (layerIndex == 1)
{
//雙手綁定
animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
animator.SetIKPosition(AvatarIKGoal.LeftHand, IKBall_1.position);
animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
animator.SetIKRotation(AvatarIKGoal.LeftHand,
Quaternion.LookRotation(transform.forward, transform.TransformDirection(new Vector3(-1f, -1.73f, 0f))));
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
animator.SetIKPosition(AvatarIKGoal.RightHand, IKBall_2.position);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
animator.SetIKRotation(AvatarIKGoal.RightHand, Quaternion.LookRotation(transform.up, transform.right));
}
}