什么是IK?
IK(Inverse Kinematics)即反向動力學,即可以使用場景中的各種物體來控制和影響角色身體部位的運動,一般來說骨骼動畫都是傳統的從父節點到子節點的帶動方式(即正向動力學),而IK則倒過來,由骨骼子節點帶動骨骼父節點,具體情況比如人物走路踩到了石頭就需要由腳的子節點來帶動全身骨骼做出踩到石頭的響應。
IK可以使人物和場景更加貼合,從而達到更加真實的游戲效果,如果大家玩過《波斯王子》或《刺客信條》系列,應該對主角的攀爬和飛檐走壁的能力印象深刻,這些都是應用了IK,使動畫貼合到具體的場景中進行的表現。
Unity3D本身已經帶有了IK的功能(http://docs.unity3d.com/Manual/InverseKinematics.html),我們接下來就對IK進行一下簡單的學習和使用。
FinalIK
該插件是對Unity本身的IK的優化和增強,可以模擬出更加真實的效果,有興趣可以看一看。
https://www.assetstore.unity3d.com/cn/#!/content/14290
實例
我們直接上手一個小例子來看看Unity3D中的IK應該如何使用,我們會創建一個場景,使人物的頭部始終面向一個點,同時創建四個點控制人物的手和腿的移動。
我們在場景中添加一個人物和5個小球,如下:
根據Unity官方的文檔給出的資料來看,首先必須在需要使用IK動畫的Animator的層上開啟“IK Pass”,如下圖所示:
只有開啟了這個選項,系統才會調用IK相應的方法。
下面我們為這個人物添加一個腳本,如下:
1 using UnityEngine; 2 using System.Collections; 3 4 public class TestIK : MonoBehaviour 5 { 6 public Transform lookAtTarget; 7 8 public Transform leftHandTarget; 9 public Transform rightHandTarget; 10 public Transform leftFootTarget; 11 public Transform rightFootTarget; 12 13 private Animator _animator; 14 15 void Start() 16 { 17 _animator = this.GetComponent<Animator>(); 18 } 19 20 void OnAnimatorIK(int layerIndex) 21 { 22 if(_animator != null) 23 { 24 //僅僅是頭部跟着變動 25 _animator.SetLookAtWeight(1); 26 //身體也會跟着轉, 弧度變動更大 27 //_animator.SetLookAtWeight(1, 1, 1, 1); 28 if(lookAtTarget != null) 29 { 30 _animator.SetLookAtPosition(lookAtTarget.position); 31 } 32 33 _animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1); 34 _animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1); 35 if(leftHandTarget != null) 36 { 37 _animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHandTarget.position); 38 _animator.SetIKRotation(AvatarIKGoal.LeftHand, leftHandTarget.rotation); 39 } 40 41 _animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1); 42 _animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1); 43 if(leftHandTarget != null) 44 { 45 _animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandTarget.position); 46 _animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandTarget.rotation); 47 } 48 49 _animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1); 50 _animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1); 51 if(leftHandTarget != null) 52 { 53 _animator.SetIKPosition(AvatarIKGoal.LeftFoot, leftFootTarget.position); 54 _animator.SetIKRotation(AvatarIKGoal.LeftFoot, leftFootTarget.rotation); 55 } 56 57 _animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1); 58 _animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1); 59 if(leftHandTarget != null) 60 { 61 _animator.SetIKPosition(AvatarIKGoal.RightFoot, rightFootTarget.position); 62 _animator.SetIKRotation(AvatarIKGoal.RightFoot, rightFootTarget.rotation); 63 } 64 } 65 } 66 }
需要注意的是,控制IK的腳本必須添加到OnAnimatorIK方法中才會生效,下面看下效果圖: