02 - 引擎中的高级动画技术
本文将对游戏引擎中的高级动画技术做一些介绍,比如动画的混合,动画状态机,IK 技术,动画重定向等。
动画混合
在游戏中,一个或多个动画序列帧需要以特定的规则组合贡献给最终的角色,这种规则就是动画混合。动画混合是游戏引擎中动画模块的重要组成部分。
线性插值混合
可以用 LERP 在多个动画序列帧之间进行差值,以达到数学上的混合效果。需要和前面单个序列帧的不同关键帧之间插值作区分。
计算混合权重
需要按照混合权重进行插值计算。以走路动画和跑步动画的插值为例,选择当前人物速度、触发走路动画和跑步动画的速度作为计算混合权重的参考值,计算出两动画各自的混合权重,然后进行插值。
对齐混合时间线
由于两动画播放的时间还不一样,如何在播放时间不一样的动画里选关键帧插值很重要。首先要求做动画的艺术家将动画的形式尽量一致,如必须是循环的,都是左脚一步右脚一步。然后要将两个动画的时间线归一化,方便插值计算。
混合空间
以玩家的方向移动为例,来看看动画的混合空间是什么。
一维混合空间
目前只有一个自变量:玩家的移动方向。因此就是 1D 混合空间。其中,采样点可以有多个,例如向前移动,向左移动,向右移动等。
二维混合空间
除了移动方向外,实际上还有速度这个自变量。这样就得到了一个二维的混合空间,其中每个采样点均为一种动画素材。
此外,在艺术家的要求和真实性考虑下,动画采样点往往是不均匀的。
我们在计算动画混合时,也不需要去计算所有种类动画的混合,这太麻烦了。而是利用 Delaunay 三角化,将采样点划分为一个个三角形,根据三角形重心坐标插值找到采样点所属三角形,最后只混合三角形三个顶点上的动画。
骨架遮罩混合
有时候我们需要在做一段动画的同时做另一段动画,这时候就需要用到骨架遮罩,让上半身做上半身的动画,下半身做下半身的动画,最后混合到一起。
附加混合
在动画混合全部做完后,如果还想让它做额外的动画,可以使用附加混合添加一个差分动画做修饰。例如一直在点头。
这种混合要做的很谨慎,因为它是基于其他混合的叠加,稍有不慎就会发生一些异常现象,例如一些扭曲。
动画状态机 ASM
有时候也会碰到动画状态切换的问题,和上面动画灵活过渡的动画混合不同。例如简单的跳跃操作由三个小动画组成,分别对应三个状态,它们之间有序切换。
定义
状态机由各种节点和箭头组成,其中节点可以是上面提到的混合空间,也能是序列帧动画。
而箭头则是状态切换的条件 (Transition),例如玩家要跳跃时,要从 Idle 状态切换到 jump_start_from_idle 状态。需要有起点和终点索引信息,以及是否要混合插值。
例如 UE 引擎的动画状态机,双箭头是状态切换条件,连接状态节点。
CrossFade
这是状态切换间常用到的过渡方法,分为平滑过渡和冰冻过渡两种:
此外,还有多种控制过渡程度的曲线供艺术家选择:
多层状态机
早期可以给角色设置多层状态机,每层状态机独立控制角色的一些动画。
动画混合树
现在人们开始使用动画混合树来代替多层状态机了,它的思想基于表达式树,通过对一些动画做 “表达式运算”,从而得到最终的动画。
节点
动画混合树有多种节点,接下来看看有什么。
LERP 混合节点
分为简单的双通道线性混合节点与多通道线性混合节点两种,区别在于混合权重的输入。
附加混合节点
UE 引擎动画混合树的节点则更加泛化灵活,叶子节点除了可以是动画序列帧外,还能是混合空间、ASM 等。
表达多层状态机
动画混合树也能表达多层状态机,可以说它是多层状态机的超集。
控制变量
在动画混合树中,会定义大量暴露给 GamePlay 系统的控制变量,以改变混合树的行为,获取实时输出。
反向动力学 IK
之前说的都是前向动力学的内容,由因得果;而反向动力学 IK (Inverse Kinematics) 则要求你根据约束好的结果求解初始状态的关节是什么样。
两骨骼约束 IK
假设要控制一个角色行走,为了能让它的脚自适应地形,需要用到 IK。容易实现的 IK 是双骨骼(三关节)约束的 IK,知道两条腿的信息便能根据三角学知识求出大腿和小腿的摆动幅度。
但实际上在 3D 空间,两骨骼约束 IK 的解是一个圆环,因此会有下图这种解不可控的情况。
为了让结果可控,可以用一个方向向量进行约束,只使用该方向上的解。
多骨骼 IK
除了双骨骼(三关节)IK 外,还有更复杂的 IK,例如下图中的各种 IK,涉及到的关节很多。
多关节 IK 的求解很复杂,首先计算过程是高维度的,其次求出来的解有很多、唯一解或无解。
计算可达性
在正式求解多骨骼 IK 时,需要计算它的可达性。一种方法是把所有骨骼拉直,看看能不能到达目标点。另一种方法是把所有骨骼往最长的骨骼那边折,看看能不能到达目标点。
解的合理性
对于骨骼 IK 还要注意解的合理性,例如人体关节是不能乱转的,具有约束性。
常用算法
对于多 IK 约束的求解,常用到启发式算法。这类算法可以较高效地应对高维求解问题,可以只求出近似解而加快计算效率。
循环坐标下降法 CCD
从末端关节开始,尽量让所有关节都靠近目标点,进行多次迭代求解。
CCD 算法还有一些优化:
给每个关节的目标点设置一个容忍区间,这样可以让动作看起来更加合理些。
限制每个关节的旋转角度,越靠近根节点的关节角度越小,使结果更加平滑舒服。
前后向迭代法 FABRIK
和 CCD 不同,FABRIK 从关节位移角度求解 IK。它会经历若干组前向 & 逆向 IK 求解:
- 前向求解从末端关节开始,让它尽量靠近目标点,然后让其他关节适应变化。
- 逆向求解从根节点关节开始,由于前向求解的适应变化更改了根节点位置,需要将根节点尽量靠近更改前的位置。
这样反复迭代几次后便能得到 IK。
FABRIK 应对关节间约束的方法是,在关节点向目标点的垂直平面做投影,然后让关节点尽量靠近投影点。
多目标点 IK
实际上目标点不止有一个,例如攀岩时目标点是四肢。
如果使用上面的普通 CCD 和普通 FABRIK 求解,会导致关节来回摆动。实际上 CCD 和 FABRIK 也是有对多目标点的处理方法,待我补充 TODO。
常用算法
雅可比矩阵求解
雅可比矩阵常用于向量运算,给定函数 fx 和 x 的取值集合,那么它们的雅可比矩阵就是 fx 和所有 x 取值一阶导的集合。
关节移动微分的求解如下,需要知道关节旋转角度的微分。
可以利用雅可比矩阵求解移动角度微分,用移动角度微分正向求解移动微分,然后进而计算新的移动角度微分以逼近目标点。
其他方法
此外还有其他方法,比如基于物理的算法,PBD 和 XPBD。
挑战
IK 还面临以下问题:
研究热点
IK 的研究热点如下:
添加混合和 IK 后的动画管线
表情动画
理论基础
面部肌肉
表情由复杂的面部肌肉系统产生:
表情编码系统
早期电影行业为所有表情编码,为游戏行业的表情系统奠定基础,不同 AU 可以自由组合。
苹果公司则对表情编码系统做了简化,总结出 28 个核心表情编码。
于是游戏行业只需做出这些表情动画,然后进行混合就行。但要注意的是,当两个表情混合时,张嘴 + 不张嘴会线性插值出半张嘴的表情,出错了。这是将整张脸的表情存储起来导致的。
方法
形变动画
因此有了形变动画,它不存储整张脸的信息,而只存储表情形变的顶点偏移信息。形变动画的数据存储和计算量随着面部信息的提升而提升。
骨骼动画
此外,对于眼珠转动以及一些夸张的表情,则需要用到骨骼动画。
形变动画和骨骼动画也是捏脸系统的基础。
UV 贴图表情动画
对于非真实感风格的游戏,则可以用 2D 贴图做表情动画,效果也很不错。
肌肉模型动画
现在也有人在研究如何用肌肉模拟表情动画,结果很真实。
应用 —Metahuman
虚幻引擎的 metahuman 则是表情动画应用的集大成者,十分真实。
动画重定向
为每个角色单独指定一套动画显然是不合理的,因此需要动画重定向技术(Animation Retargeting)将同一套动画应用到不同人物上。这需要将源角色的源动画重定向到目标角色的目标动画上。这个过程通常用其他软件离线进行。
做法
忽略源关节和目标关节的偏移
对于源关节和目标关节间的偏移,我们选择忽略他们。
保持原有的绑定姿势
如果动画里存储的是关节的绝对信息,那么未经处理直接重定向过来会影响目标角色原有的绑定姿势,需要处理一下。或者让动画存储关节的相对信息,例如相对旋转等。
通过尾椎骨高度进行微调
有时动画重定向会给目标角色带来高度偏移问题,可以通过相似三角形法则,将两角色尾椎骨和地面连线,走一段路后按比例计算,微调目标角色的偏移。
进行转换
在重定向后用 IK 锁死脚
还需要在重定向后用 IK 锁死脚,例如下图中,使用左边作为源,右边两个为目标,重定向源动画后发现双脚位置不对,需要用 IK 将双脚锁在地上。
不同骨骼的重定向
有时候会碰见具有不同骨骼层次结构的重定向,这需要一些算法来解决。
容易解法
一种容易的方法是,找寻骨骼间的映射关系,然后逐关节进行简单映射。这是英伟达 Omniverse 系统的解法。
未解决的问题
- 角色自穿模问题:将一个体型小的角色动画重定向到体型大的角色后,大角色可能会出现穿模。
- 语义问题:例如鼓掌动画,手应该接触,但有时候重定向后手不会接触。
- 重定向后角色是否看起来自然。