用 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 分两段执行:
- Squad phase:通过
PushSquadMovementIntentModifier注册的 Modifier 先执行,适合整支小队共享的战术状态。 - 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:
SquadActor绑定到小队宿主。ModifierSet指向共享资产;只在该状态独有时使用Inline Modifier Set。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 有三个阶段:
阶段 | 说明 |
|---|---|
| Driver 尝试接管该 Unit。返回 false 时本轮不会进入 active driver 状态。 |
| Driver 持续把最终 Intent 写入项目移动实现。CharacterMovement Driver 会写速度,并在需要时应用朝向。 |
| Intent 无效、 |
内置 UGAIS_UnitMovementIntentDriver_NoOp 只表示显式空策略;它接受权威端 Unit,但不移动。UGAIS_UnitMovementIntentDriver_CharacterMovement 面向 ACharacter + UCharacterMovementComponent,可写 MaxWalkSpeed,并用 DesiredOrientation 控制 AIController Gameplay Focus 或角色旋转。
完整场景:小队冲锋
- 在 SquadDefinition 中设置正常的
DefaultMovementIntentResponseSettings,并配置 CharacterMovement Driver。 - 创建
MI_Modifier_Charge:MovePolicy = ForceMove,SpeedMultiplier = 1.5,追加冲锋标签,DriverPolicy = Apply。 - 在小队 StateTree 的
Charge状态添加Task: Run Squad Movement Intent Modifier Set,指向该资产,PriorityWithinScope = 100。 - 进入
Charge后,所有成员的最终 Intent 应显示更高DesiredSpeed,bShouldMove = true,并保留阵型槽位生成的目标位置。 - 退出
Charge后,Task 自动 pop Handle。下一次解析回到 Definition 默认响应;Driver 释放不再需要的覆盖,并恢复它持有的原始移动控制状态。
排错清单
症状 | 检查 |
|---|---|
Task 进入即 Failed | Actor 是否有效且有 authority,Squad 是否 Active,ModifierSet 是否包含有效 Modifier。 |
Squad Modifier 没覆盖 Unit 结果 | 是否被更晚执行的 Unit phase 或更高 |
Intent 正确但单位不动 | |
冲锋退出后仍保持高速 | StateTree 是否真正退出该状态,Handle 是否被 pop,Owner 是否仍有未清理 Modifier。 |
多次进入后效果叠加 | 是否手动 push 后未保存 Handle,或 Owner 清理没有覆盖异常退出路径。 |
Modifier 偶发失效 | |
调试时按“Modifier 顺序 -> 最终 Intent -> Driver 激活 -> Owner/Handle 清理 -> StateTree 退出”逐层看。最终 Intent 正确但 Driver 未激活,问题在移动接入;Modifier 顺序不对,先调优 PriorityWithinScope 和 Squad/Unit phase 选择。
