MotionWarping是什么
Motion根运动(RootMotion)
传统方案中动画只做原地表现,角色的移动由Gameplay程序算出,可控性很强,但缺点是动画和位移不能做到很好的匹配,容易出现滑步
RootMotion使用动画根节点的运动变换信息来驱动我们游戏中人物移动,可以使得人物位移曲线很好贴合动画
但完全采用动画运动变换信息就意味着可控性很差,动画里设定的位移轨迹是怎样,还原出来就是怎样,不能和环境进行交互
常见例子:
主角播放动画触摸物体
如果不在指定位置播放动画的话会出现
攀越障碍物
如果障碍物变高了,就跳不过去了
对于这类问题,常见的解决方案是:
- 将人物通过程序移动到指定位置,再进行动画位移
- 目前项目里攀顶也是会将人物移动到指定位置再进行动画位移
- 如果处理不好很容易出现不自然
Warping扭曲
根运动扭曲,即对动画资产中采样出来的根运动变换信息进行扭曲,加强可控性。
简单讲就是动态去调整动画中的运动曲线,使其更贴近目标位置。
- 拆解原先动画为三段
- 每一段动画都有目标位置(带颜色的点)
- 动态去修正每一段的运动轨迹
怎么去Warping
下面简单列举UE中提供的方案,详细的算法还在理解中…
Scale类型
很自然的想法,攀越中位移不够或者位移不需要那么长,那直接把位移数据进行缩放不就行了。
但直接整体按固定倍数缩放(均匀地改变动画的比例),效果自然没那么好
不能处理指定目标,比如上面第一个例子中,去触摸一个物体
1 | // 还要考虑旋转,这里就不举例了,大致就是简单的去缩放 |
Warp类型
Simple Warp/Skew Warp
扭曲游戏对象的根骨骼运动,使其匹配关卡中扭曲窗口末尾的动画位置和旋转
简单理解下应该是每帧去修正运动偏移,使其运动方向贴近GamePlay传入的目标
扭曲的目的就是将当前根运动偏移扭曲成向世界空间目标扭曲的根运动偏移,所以我们需要构建一个变换矩阵
橙线ToRoot是根运动的目标点,绿线ToWorld是Gameplay传入的世界空间的目标点,蓝线Translation是当前的根运动偏移
下面是Skew Warp变换矩阵的生成步骤:
- 以角色【Z轴向量】与【根运动目标向量】为【平面】,【根运动目标向量】为【Z轴】构建一个【变换空间】。将【根运动目标点】和【世界空间目标点】以及【当前根运动偏移】变换到这个空间内。构建这个变换空间的目的是为了方便我们构建错切矩阵。示意图中的红蓝绿轴就是这个变换空间的XYZ。
- 通过【根运动目标向量】到【世界空间目标向量】的【投影缩放】构建一个X轴缩放矩阵。
- 根据【根运动目标点】和【世界空间目标点】的垂直面的【夹角AngleY】以及【根运动目标点】和【世界空间目标点】的水平面的【夹角AngleZ】分别构建垂直面和水平面的错切矩阵。
- 最终将这个矩阵变换应用到【当前根运动偏移】。再将其逆变换到世界空间,就得到了世界空间的扭曲后的根运动偏移。
Adjustment Blend Warp缩放
上面提到的都是基于Root骨骼的缩放,如果计算的结果与原动画偏差较大,难免会回到匹配不上动画导致滑步。
Adjustment Blend理论上可以对任意骨骼进行缩放,因此Adjustment Blend Warp缩放支持配置,针对ik骨骼进行缩放。
比如对带脚步移动的RootMotion动画应用Adjustment Blend Warp缩放,不仅能够灵活缩放位移,配合TwoBone IK,还能规避缩放位移导致的腿部滑步表现。
解决方案
- UE5,已内置引擎中,https://dev.epicgames.com/documentation/zh-cn/unreal-engine/motion-warping-in-unreal-engine
- Unity,一如既往的只有第三方插件支持,https://assetstore.unity.com/packages/tools/animation/motion-warping-climb-interact-270046