主流给角色做动画用的是动画状态机,虽说做的好也能很丝滑(但我做不好),但我要用虚幻的另一种做动画的方式——运动匹配。
导入模型的时候VRM4U很贴心的给每个角色加了IK绑定和与虚幻默认角色的动画重定向,所以,接下来我们做动画的核心思路是,给虚幻默认角色做运动匹配(它的资源很好找),然后重定向到其他角色上。
本来以为重定向是我不成熟的想法,结果官方的动画示例也是用的重定向。
研究官方的示例项目
创建第三人称项目会带着Lyra角色(虚幻默认角色),虚幻官方有这么一个项目,里面有500个可以拿来用的动画。
本来是想着把里面的动画拿出来,但打开项目后发现,这个项目的蓝图挺有研究价值的。
动画蓝图节点我只会用很少一部分,我仔细研究了每个他用到的节点,读了他每一个核心逻辑。
但是事实上有很多东西并不明白,对于这些东西,我选择Copy~
运动匹配比想象中的简单,比想象中的复杂。
动画分类
首先,动画是要分好类的,因为运动匹配虽然能选择自然的动画,但是并不能很好的选择符合情景的动作,像是,不能正确选择跑步和走路的动作。
官方把动作分成了以下分类:
待机
走路停下
跑步停下
低处落下停下
高处落下停下
原地转圈
开始走路
走路循环
转弯走路
转身然后开始走路
从中断姿势开始走路
轻走路往下跳
重走路往下跳
开始跑步
跑步循环
转弯跑步
转身然后跑步
从中断姿势开始跑步
轻跑步往下跳
重跑步往下跳
跳跃
远跳跃
从中断姿势浮空
中断姿势主要用于处理爬墙、攀越之类的动作,它们不与上述分类一起检索,触发时会使用动画蒙太奇打断上述检索出来的动画内容。
越过,隔了一个比较窄的障碍物
越下,隔了一个比较窄的障碍物,但障碍物对面没有地面
越上,障碍物很宽,可以站在上面
根运动
鼠标X方向上旋转镜头时(对应角色的Z旋转),胶囊碰撞体会旋转,并带动骨骼网格体和相机一起旋转。
另一种做法是,旋转相机,不转胶囊碰撞体,这样角色就不会永远背对相机了。
还有一种做法是,旋转胶囊碰撞体,给动画蓝图添加偏移根骨骼节点,这样在胶囊体动的时候,骨骼网格体虽然也动,但骨骼和蒙皮会有自己的想法,保持偏移。
使用这种做法,可以让动画更加自然。
加法动画
像着色器的混合模式,除了一般的,在两个姿势中间插值,虚幻还有另一种动画混合模式——加法混合。
使用加法混合的动画需要在动画序列里面启用Additive。
普通的动画也可以在蓝图中通过创建动态Additive节点变成加法动画。
选择器表
目前虚幻有一个叫Chooser的实验插件,在官方的示例项目里面使用了,用来根据一些变量的值筛选数据,可以用来取代乱七八糟的If判断。
注意事项
在动画重定向时,除了要保证动画看起来没问题,根骨骼也要正确。
对动作匹配不了解的我,以为这是动作匹配的问题,这个问题我找了好久好久···
需要在重定向器里面把根骨骼的平移模式改成全局缩放。
如果先迁移了动画,重定向时把动画事件蓝图也迁移过来,不然脚落地什么的事件都是None,还得重新重定向。
正式开始运动匹配
其他动画部分就不说啦,只看运动匹配的核心
基础
动作匹配并不神秘,也并没有太强大,很多东西都要程序去实现,并不能开箱即用。
动作匹配通过模式去匹配当前的运动轨迹和已有动画的运动轨迹(包括了根骨的运动轨迹和可选的其他骨骼的运动轨迹),取最接近的动画。
为了传递动画时方便,这些动画放在动画数据库中(单个的动画也能传递)
有一个函数,传入很多动画数据和当前的轨迹,返回一个动画。
动画图表有一个节点,帮我们自动去调那个函数。
只是用过去的轨迹往往不准确,于是又提供了几个函数,传入过去的轨迹,用来预测未来的轨迹。
蓝图有个组件,帮我们自动调上面的函数。
定义状态
动画蓝图里变量乱糟糟的很不舒服,于是我把所有的状态变量放在了一个结构体中,如图

当然,这些变量都不是凭空产生的,这都是计算出来的,出于线程安全考虑,这些变量的计算都是在动画蓝图的Update中进行的,计算后存储在动画蓝图的一个变量内,供动画蓝图的动画部分使用(因为蓝图Update部分是游戏线程,而动画部分是另一个线程)
然后就有啦这个壮观的蓝图:

准备动画数据和选择器表
参照官方示例,创建多个动画数据库,放不同类型的动画,然后再选择器表里筛选数据库。

查表
创建一个运动匹配动画节点然后绑定更新时蓝图函数,给这样子的逻辑,这会在每一帧查询一次选择器表,并且在关键状态改变时打断当前动作,进行新的动作。

预测轨迹
运动匹配的最后一步,记录和预测轨迹,按照官方文档,这里要用到记录轨迹的蓝图组件,但官方的示例项目并没有使用,而是调用特定的函数手动预测路径。
首先是,加在动画图表末尾的,用来记录骨骼历史的节点:

其中需要把匹配模式中使用的骨骼加进去:

这个节点会每帧记录一次轨迹到数组中,然后我们参考(抄)官方的预测函数
重定向
本来是打算重定向的,但是我的模板角色和其他角色的骨骼是相同的,意料之外的能够直接驱动,于是就暂时先不做重定向啦。