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系统的解法。
未解决的问题
- 角色自穿模问题:将一个体型小的角色动画重定向到体型大的角色后,大角色可能会出现穿模。
- 语义问题:例如鼓掌动画,手应该接触,但有时候重定向后手不会接触。
- 重定向后角色是否看起来自然。
参考资料
- GAMES104 (boomingtech.com)