U3L18-6——动画IK控制

在2D骨骼动画里已经讲过一些关于IK的内容 ——> U3L16-1-d——2D Animation 反向动力学IK

IK

在骨骼动画中,构建骨骼的方法被称为正向动力学
它的表现形式是,子骨骼(关节)的位置根据父骨骼(关节)的旋转而改变
用我们人体举例子
当我们抬起手臂时,是肩部关节带动的整个手臂的运动,用父子骨骼理解的话就是父带动了子

而IK全称是Inverse Kinematics,翻译过来的意思就是反向动力学的意思
它和正向动力学恰恰相反
它的表现形式是,子骨骼(关节)末端的位置改变会带动自己以及自己的父骨骼(关节)旋转
用我们人体举例子
当我们拿起一个杯子的时候是用手掌去拿,以杯子为参照物,我们移动杯子的位置,手臂会随着杯子一起移动
用父子骨骼理解的话就是子带动了父

本章代码关键字

1
2
3
4
5
6
7
8
9
10
11
12
private void OnAnimatorIK(int layerIndex) { }    //主要处理IK运动相关逻辑的函数,在Update之后LateUpdate之前调用
animator.SetLookAtWeight() //设置头部IK权重
animator.SetLookAtPosition() //设置头部看向位置
AvatarIKGoal.LeftFoot //表示左脚的IK点的枚举
AvatarIKGoal.RightFoot //表示右脚的IK点的枚举
AvatarIKGoal.LeftHand //表示左手的IK点的枚举
AvatarIKGoal.RightHand //表示右手的IK点的枚举
animator.SetIKPositionWeight() //设置某个四肢末端位置的IK权重
animator.SetIKPosition() //设置某个四肢末端位置的IK点
animator.SetIKRotationWeight() //设置某个四肢末端角度的IK权重
animator.SetIKRotation() //设置某个四肢末端角度的IK点
private void OnAnimatorMove() { } //主要处理动画移动以修改根运动的回调逻辑的函数,在Update之后LateUpdate之前调用

IK反向动力学控制对于我们的意义

IK在游戏开发中的应用

  1. 拾取某一件物品
  2. 持枪或持弓箭瞄准某一个对象

等等

如何进行IK控制

  1. 在状态机的层级设置中 开启 IK 通道(IK Pass)

    image

  2. 继承MonoBehaviour的类中,Unity定义了一个IK回调函数: OnAnimatorIK

    我们可以在该函数中调用Unity提供的 IK相关API 来控制IK

Animator中的IK相关API

OnAnimatorIK()

1
private void OnAnimatorIK(int layerIndex) { }

我们可以在该函数中调用Unity提供的IK相关API来控制IK

头部IK的API相关

有权重和看向位置,一般都是先设置权重再设置看向位置

头部IK权重

有五个参数,分别是:

weight:LookAt全局权重 0-1
bodyWeight:LookAt时身体的权重 0-1
headWeight:LookAt时头部的权重 0-1
eyesWeight:LookAt时眼镜的权重 0-1
clampWeight:0表示角色运动时不受限制,1表示角色完全固定无法执行LookAt,0.5表示只能够移动范围的一半

1
animator.SetLookAtWeight(1, 0.5f, 0.5f);
头部IK看向位置

最好先设置头部IK权重,再设置看向位置
参数为Vector3,即看向的位置

1
animator.SetLookAtPosition(lookPos.position);

四肢末端IK枚举

接下来在设置IK时,需要这个枚举来确认四肢末端

1
2
3
4
5
6
7
8
//UnityEngine命名空间内,AvatarIKGoal的定义
public enum AvatarIKGoal
{
LeftFoot,
RightFoot,
LeftHand,
RightHand
}

四肢IK相关

位置和角度,权重与位置,对应四个API,且最好先设置权重再位置或者角度,位置和角度是否一起使用取决于你的需求,例如是否要手掌指向哪里

IK位置权重

第一个参数,四肢末端IK枚举;第二个参数,权重(0-1)

1
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
IK对应的位置

该方法将改变四肢的位置(但不改变其角度),第一个参数,四肢末端IK枚举;第二个参数,IK点位置

1
animator.SetIKPosition(AvatarIKGoal.RightHand, RightHandIKPos.position);
IK角度权重

第一个参数,四肢末端IK枚举;第二个参数,权重(0-1)

1
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
IK对应的角度

该方法将改变 手掌的手指的指向的角度 或者 脚的脚尖指向的角度(但不改变其位置),第一个参数,四肢末端IK枚举;第二个参数,IK点的角度

1
animator.SetIKRotation(AvatarIKGoal.RightHand, RightHandIKPos.rotation);

OnAnimatorMove()

当动画本身包含了根物体移动时,还要处理对象移动相关时,可以在这个函数里写移动相关逻辑,相比 Update() 内写移动改变了调用时机,更加保险

1
private void OnAnimatorMove() { }

关于OnAnimatorIK和OnAnimatorMove两个函数的理解

我们可以简单理解这两个函数是两个和动画相关的特殊生命周期函数
他们在Update​之后LateUpdate​之前调用
他们会在每帧的状态机和动画处理完后调用
OnAnimatorIK​在OnAnimatorMove​之前调用
OnAnimatorIK​中主要处理 IK运动相关逻辑
OnAnimatorMove主要处理 动画移动以修改根运动的回调逻辑

他们存在的目的只是多了一个调用时机,当每帧的动画和状态机逻辑处理完后再调用