排错流程
GAIS 的问题通常不是单点错误,而是请求在某一层没有交给下一层:输入没有构造成命令,命令没有被 CommandSystem 接收,Command 层没有接管,Queue 任务没有完成,Tactical Assignment 没有解析出命令,或者小队/阵型只生成了意图但项目移动层没有消费。排查时按阶段缩小范围,比同时改资产、蓝图和 StateTree 更可靠。
相关文档:先看 GameplayDebugger 定位运行时状态,再回到 参数参考 校对字段。阵型和 Movement Intent 的细节排查见 FormationEditor 与槽位诊断。
命令没有进入 Current
现象:调用 Issue Command 后,GameplayDebugger 的 CommandSystem Current 仍是 None,Last 也没有有用结果。
优先检查:
- 被命令对象是否为 Pawn/Character,且 Pawn 上是否有
UGAIS_CommandSystemComponent。 FGAIS_CommandData.Definition是否有效。- MultiVariant 命令的
Index是否有效。 - 命令
TargetType是否和Target、bHasLocation、Location对齐。 CanObeyCommand是否返回 missing、blocking 或 error tags。- 是否在客户端直接下发了应由服务端/权威侧处理的命令。
不要先改 StateTree。命令没进 Current 时,执行层还没开始工作。
命令进入 Current 但单位不动
现象:CommandSystem Current 有命令,但角色没有行为,或 Stack/Queue 看不到对应任务。
优先检查:
- Stack 面板中 RequestedLayer 是否选择了 Command,以及 AppliedLayer 是否已完成切换。
- 命令的
GetExecutionDefinition是否返回有效执行配置。 - 若使用 StateTree 执行配置,Command 层 StateTree Schema、Blackboard key 和命令上下文是否匹配。
- Queue 面板是否有 CurrentTask、PendingTask 或最新失败 reason。
- 项目移动、GAS、Ability 或自定义执行逻辑是否真正被调用。
如果 Current 有命令但 Stack 的 Applied 层不是 Command,问题通常在 ExecutionDefinition 或它建立的路由。如果 Stack/Queue 正常但单位不动,问题多半在项目执行层。
命令长期不结束
现象:单位执行了行为,但 Current 长期不清空,后续队列不推进。
优先检查:
- ExecutionDefinition 是否在成功、失败或取消时经由精确 execution handle 回调命令结果。
- StateTree、Ability 或项目任务是否在完成、失败或超时时上报。
- GAS/Ability 结束事件是否回到命令回调。
- 命令需求标签是否在运行中变化,导致取消后又被项目逻辑恢复。
- Queue 的 CurrentTask elapsed/timeout 是否异常增长。
不要用 ClearCommands 掩盖这个问题。清空队列能恢复现场,但真正缺的是执行层结束信号。
新命令没有打断旧命令
现象:玩家点击新目标或 AI 下发新任务后,旧命令仍继续执行。
优先检查:
- 旧命令的
CancellationPolicy是否为Cancelable。 - 新命令是
IssueCommand、EnqueueCommand还是 Insert 系列入口。 - 旧命令的 ExecutionDefinition
CancelExecution是否只释放该 execution 的项目执行层状态。 - Queue 中是否只是追加了新命令,而不是立即执行。
- LastResult 和 ReasonTag 是否显示取消失败或策略拒绝。
如果想实现 Shift 排队,用 EnqueueCommand;如果想立即响应,用 IssueCommand 并确认旧命令策略允许被替换。
Tactical Assignment 没有分配
现象:计划运行了,但没有 Actor 被分配命令。
按 GameplayDebugger 的 Tactical Assignment 数字逐层看:
- Actor pool 为 0:Assignee Source 没有产出候选,或 ContextActor 不对。
- Target pool 为 0:Target Source 没有产出目标,或目标没有转换成
FGAIS_CommandTargetData。 - Actors before 有值 after 为 0:Assignee Filter 过严。
- Targets before 有值 after 为 0:Target Filter 过严,常见是队伍态度、SourceTag 或 HasActor/NoActor 不匹配。
- Candidates 为 0:Intent 解析、命令可执行性或目标合法性失败。
- Selected 为 0:Allocator、目标容量、ExistingTargetUsage 或 location tolerance 阻止选择。
- Assigned/Unassigned 有失败 reason:按
NoResolvedCommand、CannotObeyCommand、InvalidTarget、MissingCommandSystem分别回查。
不要在 Allocator 里修 Source 或 Filter 问题。Allocator 只负责从已评分候选里选最终配对。
NoResolvedCommand
现象:Tactical Assignment 有候选 Actor 和目标,但候选无法把 IntentTag 变成具体命令。
优先检查:
- Batch 的
IntentTag是否与UGAIS_UnitComponent.CommandIntentMappings完全一致。 - 候选 Actor 是否带有
UGAIS_UnitComponent,或 Actor/组件是否实现IGAIS_CommandIntentResolver。 - resolver 返回的
Command.Definition是否有效。 - MultiVariant 命令的
Command.Index是否有效。 - 是否把玩家直接命令和 AI 语义意图混在同一入口里,导致 Unit 没有对应映射。
CannotObeyCommand 或 InvalidTarget
现象:Tactical Assignment 能解析命令,但无法提交,或手动命令被拒绝。
优先区分:
CannotObeyCommand:执行者不满足命令需求。看 SourceRequiredTags、SourceBlockedTags、职业、资源、死亡/眩晕/忙碌状态,以及项目覆写的CanObeyCommand。InvalidTarget:目标不满足命令需求。看TargetType、Target Actor、Location、目标标签、队伍态度、距离和项目覆写的IsValidTarget。
如果 Filter 已经筛过目标但仍然 InvalidTarget,说明 Filter 只是提前剪枝,命令级目标规则仍然更严格。应修命令规则或目标数据,不要简单放宽 Filter。
小队初始化失败
现象:Squad 面板没有有效 Definition,FormationStatus 不 ready,成员/角色/容量不符合预期。
优先检查:
SquadActorClass是否实现IGAIS_SquadActorInterface。- 小队宿主是否具备 SquadComponent、CommandSystem、AIController/Stack 等运行时契约。
SquadDefinition是否能加载,AvailableFormations是否有效。DefaultUnits和AvailableRoles是否能满足bRequired角色。- Capacity 是否已经满,或角色 Max 阻止单位加入。
- 队伍身份是否在小队宿主和单位之间保持一致。
如果小队能创建但行为不对,继续看 Formation、Slot 和 Movement Intent,而不是重新创建小队。
槽位分配异常
现象:单位加入小队,但站错槽、抢错角色、或关键槽位长期空着。
优先检查:
SlotId是否稳定且不重复。- SlotTags 与 Unit/Role 标签是否属于同一语义体系。
SlotTagMatchPolicy是否符合“必须匹配”还是“加分匹配”的预期。SlotWeightScoreMultiplier、MatchingTagScore、DistanceCostPer100Units、StableSlotScore是否权重失衡;诊断中的对应分量是SlotWeightScoreContribution。- GameplayDebugger 的 slot assignment diagnostics 中,是 tag 拒绝、距离成本、权重还是稳定性影响最大。
如果槽位分配正确但单位不移动,进入 Movement Intent 和项目移动系统排查。
Movement Intent 有值但单位不移动
现象:Squad 面板能看到 DesiredLocation、DesiredSpeed 或 bShouldMove,但角色没有移动。
优先检查:
- 单位是否有
UGAIS_UnitMovementIntentDriver或项目移动系统是否消费了MovementIntent。 bApplyDriverOnlyWhenIntentChanged是否导致持续输入没有被重复应用。- Driver apply interval 和 Movement Intent update interval 是否过大。
- DesiredLocation 是否可达,Formation 的导航投射是否成功。
- 项目移动组件、GMS、CharacterMovement 或 AI MoveTo 是否有自己的阻挡条件。
Movement Intent 是建议,不是移动所有权。GAIS 给出目标和响应强度,真正移动由项目移动层完成。
队伍态度不符合预期
现象:友军被当敌人、敌人被过滤掉,或 Tactical Assignment Team Attitude Filter 全部失败。
优先检查:
- TeamAgent 真源是在 Pawn、Controller、PlayerState 还是项目自定义对象。
UGAIS_ProjectPolicy是否指向项目自定义策略。- GameplayDebugger 的 Team 和 TeamSource 是否符合预期。
GetGenericTeamQuerySource看到的来源是否和项目设计一致。- Team Attitude Filter 的 RequiredAttitude 是否和玩法意图一致。 不要在每个 Filter 里临时修队伍态度。队伍身份应先回到 ProjectPolicy 和 TeamAgent 真源统一。
RPC 所有权不匹配
现象:客户端调用 Server Issue Command、Server Add Unit、Server Assign Role、Server Set Current Formation 或类似节点后,服务端状态没有变化。
优先检查:
- 调用是否真的发生在客户端,而不是在错误的非 owning 网络上下文。
- CommandSystem、SquadComponent 或 FormationComponent 所在 Actor 是否由该调用客户端拥有,或是否存在可用 Owner 链。
ServerLeaveSquad的 Unit Actor 是否由调用客户端拥有。- 小队宿主由 AI/服务端拥有时,是否应改为从 PlayerController 发项目 RPC,由服务端查找小队并执行权威入口。
- 服务端是否还需要额外校验队伍所属、玩家权限、资源或游戏状态。
RPC 节点可见不等于对任意 Actor 都可调用。先修正网络所有权和服务端授权路径,再检查 GAIS 成员、角色、阵型或命令逻辑。
