[專欄精選]Unity動畫系統的IK詳解

本文節選自洪流學堂公衆號專欄《鄭洪智的Unity2018課》,未經允許不可轉載。

洪流學堂公衆號回覆專欄,查看更多專欄文章。


“大智,昨天你說要給我講講IK,趁現在有空,你給我講講唄”
“IK你已經明白是什麼意思了吧?”
IK是Inverse Kinematic的縮寫,也就是反向動力學。是根據骨骼的終節點來推算其他父節點的位置的一種方法。比如通過手的位置推算手腕、胳膊肘的骨骼的位置。
“沒錯,那你能想到一些適用的場景麼?”
“嗯。。。我想想:比如角色需要拿各種不同的東西,讓角色的手能符合各種不同的東西的握持位置,這樣就不用針對每種不同的東西單獨製作動畫了!
“非常棒!這是IK最常見的一種用途。其他的用途其實還有比如:角色的頭的旋轉,這樣可以和你視角的方向一致。角色的腳的位置,這樣可以讓角色踩在地面跟貼合。
“對對對,我只想到手了。那還有其他的麼?”
“**Unity中IK能設置的部位就是5個,分別是:頭、左右手、左右腳。**所以沒有其他部位的IK了,我們常見的其實也都是這些。”

設置IK

小新:“那具體如何用呢?”
大智:“那我就用實例來給你演示下IK是如何使用的”

頭部IK

小新和大智來到了大智的工作臺前。
大智:“我們先來看看如何設置人物的頭部根據視角旋轉。需要用到這兩個API:Animator.SetLookAtPosition和Animator.SetLookAtWeight,對應的方法爲:”

public void SetLookAtPosition(Vector3 lookAtPosition);

“這個方法用來設置頭部看向的位置,比如看向你左邊的窗戶,頭就會相應的旋轉。”
“這個看起來很簡單嘛。”
“對,這個方法確實很簡單,不過還有另外一個:”

public void SetLookAtWeight(float weight, float bodyWeight = 0.0f, float headWeight = 1.0f, float eyesWeight = 0.0f, float clampWeight = 0.5f);

“這個方法用來**設置IK的權重,這個IK會和原來的動畫進行混合。如果權重爲1,則完全用IK的位置旋轉;如果權重爲0,則完全用原來動畫中的位置和旋轉。**至少要設置第一個參數,後面的幾個參數都有默認值,但是你也要了解所有參數的含義:”

  • Weight 全局權重,後面所有參數的係數
  • bodyWeight 身體權重,身體參與LookAt的程度,一般是0
  • headWeight 頭部權重,頭部參與LookAt的權重,一般是1
  • eyesWeight 眼睛權重,眼睛參與LookAt的權重,一般是0(一般沒有眼睛部分的骨骼)
  • clampWeight 權重的限制。0代表沒有限制(脖子可能看起來和斷了一樣),1代表完全限制(頭幾乎不會動,像是固定住了)。0.5代表可能範圍的一半(180度)。

大智:“有了這兩個方法你就可以實現頭部的IK了,不過還有兩點需要注意:”

1、需要勾選對應Layer的IK Pass選項(在Layer的設置裏)。
2、代碼需要寫在OnAnimatorIK這個事件方法裏面。

void OnAnimatorIK(int layerIndex)
{
    _animator.SetLookAtPosition(pos);
    _animator.SetLookAtWeight(1);
}

上面的代碼就是人物的頭部看向一個位置的代碼。需要注意的是這個OnAnimatorIK方法有一個參數layerIndex,這個就是對應的Layer的序號,只有勾選了IK Pass的layer纔會調用到這個方法裏,每個勾選了IK Pass的layer調用一次。

小新:“這樣我就能實現人物的頭跟着視角移動了,哦也”
大智:“是的哦”

手腳IK

小新:“那手腳的IK是不是也跟這個類似的?”
大智:“是的,手腳的IK是和這個類似的,不過API有些不一樣,我們來看看”

public void SetIKPosition(AvatarIKGoal goal, Vector3 goalPosition);
public void SetIKRotation(AvatarIKGoal goal, Quaternion goalRotation);

設置頭部時,因爲頭不會移動,所以只需要設置LookAt的位置,頭部跟隨旋轉即可。
但是對於手和腳,需要同時設置位置和旋轉。

goal AvatarIKGoal枚舉類型,包含:

  • LeftFoot 左腳
  • RightFoot 右腳
  • LeftHand 左手
  • RightHand 右手

goalPosition/goalRotation IK目標位置/旋轉

同樣還有設置權重的API:

public void SetIKPositionWeight(AvatarIKGoal goal, float value);
public void SetIKRotationWeight(AvatarIKGoal goal, float value);

goal AvatarIKGoal枚舉類型
value IK的權重,1代表完全使用IK值,0代表使用原動畫的值

常見的設置手部IK的代碼是(一般需要4行代碼設置一個部位):

void OnAnimatorIK(int layerIndex)
{
    _animator.SetIKPosition(AvatarIKGoal.LeftHand, position);
    _animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);

    _animator.SetIKRotation(AvatarIKGoal.LeftHand, rotation);
    _animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
}

小新:“謝謝智哥,這樣我就明白很多了。我要去改造一下我的人物角色的頭部方向和握槍!”
說着小新就跑回了自己的房間。

IK位置/旋轉調節小技巧

小新:“大智,這個IK的位置好難調整啊,我想讓角色拿槍的手能夠貼合這個槍,有沒有什麼簡單的辦法?我這調了一個多小時了,還不是特別完美。。。”
大智:“調IK是個慢活,不過呢,確實有一些小技巧在裏面。IK相關的代碼涉及到位置和旋轉,這時候不要傻傻的直接定義一個位置和旋轉來手動設置,最好的辦法是設置兩個參照物,作爲IK的位置和旋轉的參考,這樣只需要調這兩個參照物就可以了。”
小新:“對對對,這樣的話就不用去修改位置和旋轉的值,而是直接修改這倆參照物的位置和旋轉就可以了。我來試一下。”

運行時調整IK的參考位置.gif

小新:“太棒了,這樣我就能在運行時調整這個參考位置,調到一個完美的位置和角度。”
小新三下五除二,就調到了一個合適的位置和角度。
“調好了!”小新高興地喊道,隨即退出了Play狀態。
大智:“高興早了吧?你這麼就退出來了,修改的能保存下來麼?”
小新:“啊。。。我給忘了,那這怎麼辦,運行時的修改保存不下來啊。。。”
大智:“快想想,我之前教過你一個小技巧,可以保存運行時的數據,不能這麼快就給忘了吧?”
小新:“我有印象你教過我,不過這麼久一直沒實際用到過,哪能記得清啊”
大智:“那我再教你一遍,這次可得記好了。”
小新:“一定一定,再忘了我就……我就……再問你一遍,哈哈哈哈”
大智:“皮一下很開心?記好了,點擊Transform組件右上角的小圖標,可以Copy Component,在運行時點擊,退出運行後,再點擊小圖標,選擇Paste Component Values,這樣就可以將數據粘貼回來了。”

Play模式下修改了位置

  • 在Inspector的Transform的右上角,點擊齒輪小圖標,選擇Copy Component Values
  • 退出Play模式
  • 在Inspector的Transform的右上角,點擊齒輪小圖標,選擇Paste Component Values

小新:“哦~~我回憶起來了,這次絕對不會再忘記了”

總結

小新:“有了IK,人物就能更符合遊戲的需要了,而且可以根據不同的情形動態調整,人物就不會那麼呆呆的了。”
“看來小新對IK的理解還是挺深的。”

今日思考題

大智:“給你佈置個作業,去用IK把你人物的視角以及拿槍的手部位置實現一下吧”
“收到!我去也!”
“收穫別忘了分享出來!也別忘了分享給你學Unity的朋友,也許能夠幫到他。”

洪流學堂公衆號回覆專欄,查看更多專欄文章。


《鄭洪智的Unity2018課》,傾盡我8年的開發經驗,結合最新的Unity2018,帶你從入門到精通。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章