总览
UAFLayering 是 UAF 对动画分层的实验性实现。它把 layer stack、layer、内容提供者、混合提供者、Montage 兼容和运行时 layer event 拆开,目标是让上半身攻击、受击覆盖、表情/手势、Montage 插槽这类逻辑不再散落在主图里。
源码依据
重点文件:
UAFLayering/Internal/UAFLayerStack.hUAFLayering/Public/UAFLayeringTypes.hUAFLayering/Public/UAFLayeringUtils.hUAFLayering/Internal/Traits/MontageLayerTraitData.hUAFLayeringUncookedOnly/Internal/Layers/UAFLayer.hUAFLayeringUncookedOnly/Internal/Layers/UAFMontageProvider.hUAFLayeringUncookedOnly/Internal/Layers/UAFLayerContentProviderBase.hUAFLayeringUncookedOnly/Internal/Layers/UAFLayerBlendProviderBase.h
UUAFLayerStack 继承 UUAFAnimGraph。LayerStack 本质仍是一个 UAF AnimGraph 资产,只是编辑器表达和编译过程围绕“层”组织。
Layer 的编辑器结构
UUAFLayer 是 editor representation,保存:
EUAFLayerState LayerStateFName LayerNameTInstancedStruct<FUAFLayerContentProviderBase> LayerContentProviderTInstancedStruct<FUAFLayerBlendProviderBase> LayerBlendProvider
它负责创建 layer widget、创建 layer graph content traits、切换 preview visibility、重命名、校验名字和收集对象引用。注意这部分在 UncookedOnly,运行时代码不应该依赖 UUAFLayer。
Layer Event
UAFLayeringTypes.h 里定义了 FLayerStack_LayerEvent。它继承 FAnimNextTraitEvent,可以按 layer name 或 index 定位层,并指定动作:
EnableLayerDisableLayerSetFloatValue
还提供了常用属性名:
LayerWeightPropertyBlendInTimePropertyBlendOutTimeProperty
运行时概念示意:
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。它的字段说明了兼容目标:
SlotNamebAlwaysUpdateSourcebDisableSynchronizationbAutoEnableLayerWithMontagebAutoSetBlendTimesFromMontage
配套的 FUAFMontageLayerTraitSharedData 保存:
bAutoEnableLayerbAutoSetBlendTimesSlotNameLayerNameLayerStackPath
这说明 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
落地步骤:
- 新建
UAF Layer Stack,先只建BaseLocomotion和UpperBody。 BaseLocomotion继续用旧 locomotion 或一个简单 UAF graph。UpperBody用FUAFMontageProvider绑定旧 Montage slot,例如UpperBody。- 打开
bAutoEnableLayerWithMontage,让 Montage 播放时自动启层。 - 如果 Montage 自带 blend in/out,打开
bAutoSetBlendTimesFromMontage。 - 只在攻击链验证通过后,再把某个武器的 Montage 内容替换成 UAF 原生图。
验收时要看三件事:Montage 开始时 layer 是否按预期启用,Montage 结束后 layer weight 是否回到 0,切换武器时旧 slot 是否还映射到正确 layer。
使用案例:受击覆盖层
受击很适合做成独立 additive layer,因为它不应该重置 locomotion 主图:
- UAF StateTree 或 gameplay 事件写入
OverlayState = HitReact。 - Layer Event 启用
AdditiveHit层,并设置LayerWeight。 - AdditiveHit 层播放短 additive 资产,或根据受击方向选图。
- 计时结束后发 DisableLayer,或者将 LayerWeight 平滑回 0。
这样做比在主 locomotion 图里插入受击状态更稳。角色仍保持移动图的时间和同步,受击只是叠加表现。
架构分析:LayerStack 的边界
| 层类型 | 推荐输入 | 不应该承担 |
|---|---|---|
| BaseLocomotion | 移动变量、Motion Matching 结果 | 攻击、换弹、表情等覆盖状态 |
| UpperBody | 武器、瞄准、攻击、Montage slot | 地面移动状态机 |
| AdditiveHit | 受击方向、强度、衰减时间 | gameplay 伤害判定 |
| Gesture | 互动、表情、剧情动作 | 高频 locomotion 修正 |
Layer 只管动画表现。是否真的造成伤害、是否允许打断、是否进入霸体,这些都留给 gameplay 或 Ability 系统。
命名和事件规范
推荐:
- LayerName 用稳定英文名,例如
Base、UpperBody、AdditiveHit。 - 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.hUAFLayering/Source/UAFLayering/Public/UAFLayeringTypes.hUAFLayering/Source/UAFLayeringUncookedOnly/Internal/Layers/UAFLayer.hUAFLayering/Source/UAFLayeringUncookedOnly/Internal/Layers/UAFMontageProvider.h