UE5.8 Unreal Animation Framework 专题系列

UE5.8 UAF 专题(八):Layering、Layer Stack 与 Montage 兼容

解释 UUAFLayerStack、UUAFLayer、Layer Content/Blend Provider、Montage Layer Provider、Layer Event、自动启用层和混合时间同步。

总览

UAFLayering 是 UAF 对动画分层的实验性实现。它把 layer stack、layer、内容提供者、混合提供者、Montage 兼容和运行时 layer event 拆开,目标是让上半身攻击、受击覆盖、表情/手势、Montage 插槽这类逻辑不再散落在主图里。

UE5.8 UAF 专题(八):Layering、Layer Stack 与 Montage 兼容 配图
UAFLayering 把图层、内容提供者和混合提供者拆开,Montage Provider 用来兼容旧 Montage 工作流。

源码依据

重点文件:

  • UAFLayering/Internal/UAFLayerStack.h
  • UAFLayering/Public/UAFLayeringTypes.h
  • UAFLayering/Public/UAFLayeringUtils.h
  • UAFLayering/Internal/Traits/MontageLayerTraitData.h
  • UAFLayeringUncookedOnly/Internal/Layers/UAFLayer.h
  • UAFLayeringUncookedOnly/Internal/Layers/UAFMontageProvider.h
  • UAFLayeringUncookedOnly/Internal/Layers/UAFLayerContentProviderBase.h
  • UAFLayeringUncookedOnly/Internal/Layers/UAFLayerBlendProviderBase.h

UUAFLayerStack 继承 UUAFAnimGraph。LayerStack 本质仍是一个 UAF AnimGraph 资产,只是编辑器表达和编译过程围绕“层”组织。

Layer 的编辑器结构

UUAFLayer 是 editor representation,保存:

  • EUAFLayerState LayerState
  • FName LayerName
  • TInstancedStruct<FUAFLayerContentProviderBase> LayerContentProvider
  • TInstancedStruct<FUAFLayerBlendProviderBase> LayerBlendProvider

它负责创建 layer widget、创建 layer graph content traits、切换 preview visibility、重命名、校验名字和收集对象引用。注意这部分在 UncookedOnly,运行时代码不应该依赖 UUAFLayer

Layer Event

UAFLayeringTypes.h 里定义了 FLayerStack_LayerEvent。它继承 FAnimNextTraitEvent,可以按 layer name 或 index 定位层,并指定动作:

  • EnableLayer
  • DisableLayer
  • SetFloatValue

还提供了常用属性名:

  • LayerWeightProperty
  • BlendInTimeProperty
  • BlendOutTimeProperty

运行时概念示意:

UE::UAF::Layering::FLayerStack_LayerEvent Event(TEXT("UpperBody"), LayerStackPath);
Event.Action = UE::UAF::Layering::ELayerEventAction::SetFloatValue;
Event.PropertyToSet = UE::UAF::Layering::FLayerStack_LayerEvent::LayerWeightProperty;
Event.FloatValue = 0.75f;
Event.bAutoConsumeEvent = true;

// 真实代码需要按项目事件创建方式包装成 FAnimNextTraitEventPtr。
UAFComponent->QueueInputTraitEvent(MoveTemp(EventPtr));

Montage Provider

FUAFMontageProvider 是 Layer Content Provider,用于支持 legacy montages。它的字段说明了兼容目标:

  • SlotName
  • bAlwaysUpdateSource
  • bDisableSynchronization
  • bAutoEnableLayerWithMontage
  • bAutoSetBlendTimesFromMontage

配套的 FUAFMontageLayerTraitSharedData 保存:

  • bAutoEnableLayer
  • bAutoSetBlendTimes
  • SlotName
  • LayerName
  • LayerStackPath

这说明 UAF 没有强迫你立刻放弃 Montage,而是提供了把 Montage slot 映射到 layer 的桥。

项目落地

建议分层:

内容 混合策略
BaseLocomotion locomotion / idle / turn 全身
UpperBody 射击、挥砍、持物 Spine mask 或 layer blend
AdditiveHit 受击、抖动、呼吸 Additive
Gesture 表情、手势、互动 局部骨骼
MontageCompat 旧 Montage slot 自动启用和时间同步

迁移旧项目时,不要一次把所有 Montage 改成 UAF 原生图。先把 slot 映射成 Layer,然后逐个替换内容提供者。

使用案例:上半身攻击和旧 Montage 共存

很多项目已经有大量攻击 Montage。UAF Layering 的现实价值不是让你立刻删掉它们,而是把旧 Montage 放到更清楚的层里:

LayerStack: LS_Hero_Combat
  BaseLocomotion
    Content: locomotion graph
  UpperBody
    Content: weapon upper graph or Montage Provider
    Blend: spine mask, 0.15s in, 0.20s out
  AdditiveHit
    Content: hit additive graph
    Blend: additive, short decay
  Gesture
    Content: emote / interaction overlay

落地步骤:

  1. 新建 UAF Layer Stack,先只建 BaseLocomotionUpperBody
  2. BaseLocomotion 继续用旧 locomotion 或一个简单 UAF graph。
  3. UpperBodyFUAFMontageProvider 绑定旧 Montage slot,例如 UpperBody
  4. 打开 bAutoEnableLayerWithMontage,让 Montage 播放时自动启层。
  5. 如果 Montage 自带 blend in/out,打开 bAutoSetBlendTimesFromMontage
  6. 只在攻击链验证通过后,再把某个武器的 Montage 内容替换成 UAF 原生图。

验收时要看三件事:Montage 开始时 layer 是否按预期启用,Montage 结束后 layer weight 是否回到 0,切换武器时旧 slot 是否还映射到正确 layer。

使用案例:受击覆盖层

受击很适合做成独立 additive layer,因为它不应该重置 locomotion 主图:

  1. UAF StateTree 或 gameplay 事件写入 OverlayState = HitReact
  2. Layer Event 启用 AdditiveHit 层,并设置 LayerWeight
  3. AdditiveHit 层播放短 additive 资产,或根据受击方向选图。
  4. 计时结束后发 DisableLayer,或者将 LayerWeight 平滑回 0。

这样做比在主 locomotion 图里插入受击状态更稳。角色仍保持移动图的时间和同步,受击只是叠加表现。

架构分析:LayerStack 的边界

层类型 推荐输入 不应该承担
BaseLocomotion 移动变量、Motion Matching 结果 攻击、换弹、表情等覆盖状态
UpperBody 武器、瞄准、攻击、Montage slot 地面移动状态机
AdditiveHit 受击方向、强度、衰减时间 gameplay 伤害判定
Gesture 互动、表情、剧情动作 高频 locomotion 修正

Layer 只管动画表现。是否真的造成伤害、是否允许打断、是否进入霸体,这些都留给 gameplay 或 Ability 系统。

命名和事件规范

推荐:

  • LayerName 用稳定英文名,例如 BaseUpperBodyAdditiveHit
  • Event 只改变 layer weight、启用状态和 blend time,不直接改变 gameplay 状态。
  • Montage slot 和 layer name 建立一张明确映射表。
  • LayerStack 资产路径参与事件定位时,要避免重命名后无人更新。

常见坑

  • UUAFLayer 是编辑器表示,不是运行时层对象。
  • Layer event 可以按 index 或 name 定位;生产项目优先 name,index 对重排敏感。
  • 自动启用 Montage Layer 很方便,但要确认 Montage 完全 blend out 后层是否回到预期状态。
  • bAlwaysUpdateSource 会增加开销,只在 Montage 需要持续读取源输入时打开。
  • 旧 Montage 的同步组和 UAF 同步策略要单独验证,不要默认二者完全等价。

源码路径索引

  • UAFLayering/Source/UAFLayering/Internal/UAFLayerStack.h
  • UAFLayering/Source/UAFLayering/Public/UAFLayeringTypes.h
  • UAFLayering/Source/UAFLayeringUncookedOnly/Internal/Layers/UAFLayer.h
  • UAFLayering/Source/UAFLayeringUncookedOnly/Internal/Layers/UAFMontageProvider.h