用 StateTree 临时修改 Movement Intent

GAIS_Cover
YuewuDev

作者

YuewuDev

创建时间: 2026年10月12日更新时间: 2026年10月12日

目录

用 StateTree 临时修改 Movement Intent

Movement Intent 的基础值来自阵型槽位:FormationComponent 提供槽位世界变换,SquadComponent 为成员生成 FGAIS_MovementIntentResolveState,再收束为每个 Unit 的 FGAIS_SquadUnitMovementIntent。StateTree Modifier 适合处理“这个状态期间临时改变移动建议”的需求,例如冲锋、压制、列队慢行、被减速或暂停 Driver。

相关文档:基础接入见 接入 Movement Intent 到移动系统,字段含义见 小队、角色与单位参数,扩展边界见 阵型与 Movement Intent 扩展点,排查入口见 Formation Editor 与槽位诊断。

运行顺序

每次刷新 Movement Intent 时,Definition 的 DefaultMovementIntentResponseSettings 和 DefaultMovementIntentTags 先初始化 draft。Formation 槽位提供 TargetLocation、DesiredOrientation 和 SlotTags 上下文,小队平均速度写入 PredictionVelocity。

随后 Modifier 分两段执行:

  1. Squad phase:通过 PushSquadMovementIntentModifier 注册的 Modifier 先执行,适合整支小队共享的战术状态。
  2. Unit phase:通过 PushUnitMovementIntentModifier 注册的 Modifier 后执行,适合单个成员的异常状态或角色覆盖。

同一 scope 内按 PriorityWithinScope 从低到高执行,数值越高越晚执行。后执行的 Modifier 可以覆盖前面写入的 MovePolicy、DriverPolicy、速度、预测和 MovementIntentTags。

1. 创建 Modifier Set

创建 UGAIS_MovementIntentModifierSet 资产,添加一个或多个 UGAIS_MovementIntentModifier 实例。Modifier 的 ModifyMovementIntent 应只修改传入的 FGAIS_MovementIntentResolveState,不要在回调里改小队成员、阵型、命令、Ability、MovementComponent,也不要再次 push/pop Modifier。

冲锋状态常见修改:

  • 将 MovePolicy 设为 ForceMove,避免自动滞回在冲锋中停止。
  • 提高 SpeedMultiplier,或设置 bOverrideDesiredSpeed 与 DesiredSpeedOverride。
  • 追加项目语义标签,例如 GAIS.MovementIntent.Charge。
  • 保持 DriverPolicy 为 Apply,让配置的 Driver 持续消费最终 Intent。

如果该状态只想让 StateTree 或项目移动层读取 Intent,而暂时不让 Squad Driver 应用,把 DriverPolicy 设为 Suspended。这样 Intent 仍会镜像到 UnitComponent,但 Driver 会释放或不激活控制。

2. 在 StateTree 中注册临时状态

在小队 StateTree 的冲锋状态中添加 Task: Run Squad Movement Intent Modifier Set:

  1. SquadActor 绑定到小队宿主。
  2. ModifierSet 指向共享资产;只在该状态独有时使用 Inline Modifier Set。
  3. PriorityWithinScope 设为高于常规策略的值,例如 100。

Task 进入状态时会调用 PushSquadMovementIntentModifier,拿到 FGAIS_MovementIntentModifierHandle 并保持 Running。状态退出时会调用 PopMovementIntentModifier,Handle 清理后请求重新解析 Intent。

如果只修改某个成员,在 Unit StateTree 中使用 Task: Run Unit Movement Intent Modifier Set,绑定 UnitActor。它会从 UnitComponent 找到所属小队,再调用 PushUnitMovementIntentModifier。

3. 验证 Driver 激活与释放

UGAIS_UnitMovementIntentDriver 有三个阶段:

阶段

说明

ActivateMovementIntent

Driver 尝试接管该 Unit。返回 false 时本轮不会进入 active driver 状态。

ApplyMovementIntent

Driver 持续把最终 Intent 写入项目移动实现。CharacterMovement Driver 会写速度,并在需要时应用朝向。

ReleaseMovementIntent

Intent 无效、DriverPolicy 变为 Suspended、Unit 离队或小队失效时释放控制。CharacterMovement Driver 会在仍由它控制时恢复原始速度和旋转状态。

内置 UGAIS_UnitMovementIntentDriver_NoOp 只表示显式空策略;它接受权威端 Unit,但不移动。UGAIS_UnitMovementIntentDriver_CharacterMovement 面向 ACharacter + UCharacterMovementComponent,可写 MaxWalkSpeed,并用 DesiredOrientation 控制 AIController Gameplay Focus 或角色旋转。

完整场景:小队冲锋

  1. 在 SquadDefinition 中设置正常的 DefaultMovementIntentResponseSettings,并配置 CharacterMovement Driver。
  2. 创建 MI_Modifier_Charge:MovePolicy = ForceMove,SpeedMultiplier = 1.5,追加冲锋标签,DriverPolicy = Apply。
  3. 在小队 StateTree 的 Charge 状态添加 Task: Run Squad Movement Intent Modifier Set,指向该资产,PriorityWithinScope = 100。
  4. 进入 Charge 后,所有成员的最终 Intent 应显示更高 DesiredSpeed,bShouldMove = true,并保留阵型槽位生成的目标位置。
  5. 退出 Charge 后,Task 自动 pop Handle。下一次解析回到 Definition 默认响应;Driver 释放不再需要的覆盖,并恢复它持有的原始移动控制状态。

排错清单

症状

检查

Task 进入即 Failed

Actor 是否有效且有 authority,Squad 是否 Active,ModifierSet 是否包含有效 Modifier。

Squad Modifier 没覆盖 Unit 结果

是否被更晚执行的 Unit phase 或更高 PriorityWithinScope 覆盖。

Intent 正确但单位不动

DriverPolicy 是否为 Apply,Driver 是否激活成功,Unit 类型是否满足 Driver 要求。

冲锋退出后仍保持高速

StateTree 是否真正退出该状态,Handle 是否被 pop,Owner 是否仍有未清理 Modifier。

多次进入后效果叠加

是否手动 push 后未保存 Handle,或 Owner 清理没有覆盖异常退出路径。

Modifier 偶发失效

ModifyMovementIntent 是否改了成员、阵型或绑定源,触发稳定性保护。

调试时按“Modifier 顺序 -> 最终 Intent -> Driver 激活 -> Owner/Handle 清理 -> StateTree 退出”逐层看。最终 Intent 正确但 Driver 未激活,问题在移动接入;Modifier 顺序不对,先调优 PriorityWithinScope 和 Squad/Unit phase 选择。