UE5.8 Motion Warping 专题系列

UE5.8 Motion Warping 专题(三):Component、Adapter 与每帧执行链

从 UMotionWarpingComponent 的 Modifiers、WarpTargets、OwnerAdapter 讲到 UpdateWithContext、ProcessRootMotionPreConvertToWorld、Modifier 状态机和 Character/Mover 适配器。

总览

UMotionWarpingComponent 是运行时中枢。它不是动画资产,也不是移动组件,而是保存三类状态:WarpTargets 是目标列表,Modifiers 是当前活跃或等待的 root motion 修改器,OwnerAdapter 是“我该怎么从宿主身上拿 Mesh、位置、脚底和 root motion 回调”的适配层。

UE5.8 Motion Warping 专题(三):Component、Adapter 与每帧执行链 配图
组件保存目标和 Modifier,Adapter 把不同移动系统接入同一个 root motion 处理入口。

Component 保存什么

成员 作用 常见排查点
WarpTargets 运行时目标,按名字查找 名字不一致、目标未更新、Follow 失效
Modifiers Notify Window 生成的修改器 窗口没触发、状态没 Active
OwnerAdapter 接入 Character 或 Mover 组件没初始化、移动系统没绑定
SwitchOffConditions 实验性中断/暂停条件 距离或角度条件提前关掉 Warping

状态机

URootMotionModifier 的状态是 WaitingActiveMarkedForRemovalDisabled。窗口还没到时等待;播放时间进入窗口后激活;窗口结束后标记移除;被关闭或条件暂停时禁用。

Waiting
  -> Active
  -> MarkedForRemoval

Disabled can stay during the window but stops changing root motion.

每帧执行链

ProcessRootMotionPreConvertToWorld 是最关键的函数。它先调用 UpdateWithContext,后者扫描当前动画的 Notifies,发现 UAnimNotifyState_MotionWarping 就创建 Modifier。然后组件遍历 Modifiers,只对 Active 的 Modifier 调用 ProcessRootMotion

这解释了一个常见现象:目标已经写进组件,但角色不对齐。因为目标只是数据,真正修改发生在 Notify Window 内且 Modifier Active 时。

Adapter 的意义

默认 ACharacter 使用 UMotionWarpingCharacterAdapter,它把 CharacterMovement 的本地 root motion 回调接到 Motion Warping。UE5.8 的 Mover 也有 UMotionWarpingMoverAdapter,在 UMoverComponent 初始化时发现角色有 UMotionWarpingComponent 就创建适配器,并绑定 ProcessLocalRootMotionDelegate

这层设计的好处是 Motion Warping 不强依赖某一种移动系统。只要你的移动系统能提供 local root motion 处理入口,也可以写自己的 Adapter。

使用案例:窗口触发但没效果

排查顺序建议固定:

  1. 角色上有没有 UMotionWarpingComponent
  2. 组件是否初始化并创建了正确 Adapter。
  3. WarpTargets 里有没有目标名。
  4. Montage 当前时间是否进入 Notify Window。
  5. Modifiers 是否有对象,状态是否 Active
  6. ProcessRootMotion 是否返回了不同于输入的 Root Motion。
  7. CharacterMovement 或 Mover 是否真的使用了处理后的 Root Motion。

常见坑

  • 自定义 Pawn 不是 ACharacter,却以为默认适配器会工作。
  • 多个 Montage 叠加,当前产生 root motion 的动画不是你加 Notify 的那段。
  • bSearchForWindowsInAnimsWithinMontages 没开,但 Notify 加在 Montage 内部的 AnimSequence 上。
  • Modifier 被 DisableAllRootMotionModifiers 或 SwitchOffCondition 关掉。
  • 目标在组件里存在,但动画窗口的 Modifier 用的是另一个名字。

源码依据

UMotionWarpingComponent::InitializeComponent 会为 Character 创建 UMotionWarpingCharacterAdapter 并绑定回调。UpdateWithContext 扫描 Animation 或 Montage 内部动画的 UAnimNotifyState_MotionWarpingProcessRootMotionPreConvertToWorld 在非 Shipping/Test 下还受 a.MotionWarping.Disable 控制,并用 a.MotionWarping.Debug 绘制/打印调试信息。

源码路径索引

  • MotionWarping/Public/MotionWarpingComponent.h
  • MotionWarping/Private/MotionWarpingComponent.cpp
  • MotionWarping/Public/MotionWarpingAdapter.h
  • MotionWarping/Public/MotionWarpingCharacterAdapter.h
  • Experimental/Mover/Public/MotionWarpingMoverAdapter.h