什么是IK
IK是Inverse Kinematic的缩写,即反向动力学。
一般传统上骨骼动画都是由父骨骼(节点)带动子骨骼(节点)运动方式,如手臂带动手腕,即正向动力学。
而IK恰恰相反,由子骨骼(节点)带动父骨骼运动方式,或者也可以这么说:是由骨骼的终结点来推算其他父节点的位置的一种方式。如:比如跳街舞的少年用手撑着身体在地上转圈,手就是子骨骼,胳膊身体就是它的父骨骼,这时运动手就需要带动胳膊身体来移动。人物走路踩到了石头就需要由脚的子节点来带动全身骨骼做出踩到石头的响应。通过手的位置推算手腕,胳膊肘骨骼位置等
在Unity中怎么使用?
在Mecanim系统中,任何正确设置了Avatar的人形角色都支持IK功能
步骤一:开启IK功能
首先在Animator里的需要IK动画的Layer层上开启"IK Pass"(前提是创建了Animator Controller)
如下图所示:
只要开启了该选项,Unity才会调用IK的相应的方法
步骤二:在代码中调用
1.代码需要在void OnAnimatorIK()调用
2.需要设置animator中参与动画的骨骼Position,Rotation的weight的大小,如果权重为1,则完全用IK的位置旋转;如果权重为0,则完全用原来动画中的位置和旋转
3.设置所需要的Position,Rotation
设置头部的朝向
void OnAnimatorIK() {
animator.SetLookAtWeight(1); //设置IK权重 如果权重为1,则完全用IK的位置旋转;如果权重为0,则完全用原来动画中的位置和旋转
animator.SetLookAtPosition(cubeTransform.position); //设置朝向的位置
}
效果图:
设置伸手
void OnAnimatorIK() {
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1); //AvatarIKGoal.RightHand 右手
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandObj.position); //rightHandObj 目标Transform
animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandObj.rotation);
}
效果图:
IK中API详解
SetLookAtPosition
public void SetLookAtPosition(Vector3 lookAtPosition);
lookAtPosition:所朝向的目标位置
SetLookAtWeight
public void SetLookAtWeight(float weight, float bodyWeight = 0.0f, float headWeight = 1.0f, float eyesWeight = 0.0f, float clampWeight = 0.5f);
weight:全局权重,后面所有参数的系数
eyesWeight:身体权重,身体参与LookAt的程度,一般是0
headWeight:头部权重,头部参与LookAt的权重,一般是1
eyesWeight:眼睛权重,眼睛参与LookAt的权重,一般是0(一般没有眼睛部分的骨骼)
clampWeight:权重的限制。0代表没有限制(脖子可能看起来和断了一样),1代表完全限制(头几乎不会动,像是固定住了)。0.5代表可能范围的一半(180度)
SetIKPosition/SetIKRotation IK目标位置/旋转
public void SetIKPosition(AvatarIKGoal goal, Vector3 goalPosition);
public void SetIKRotation(AvatarIKGoal goal, Quaternion goalRotation);
AvatarIKGoal:枚举类型,包含:
- LeftFoot 左脚
- RightFoot 右脚
- LeftHand 左手
- RightHand 右手
goalPosition/goalRotation:目标Transform
SetIKPositionWeight/SetIKRotationWeight IK位置/旋转的权重
public void SetIKPositionWeight(AvatarIKGoal goal, float value);
public void SetIKRotationWeight(AvatarIKGoal goal, float value);
AvatarIKGoal:同上
value:IK的权重,1代表完全使用IK值,0代表使用原动画的值