命令扩展点
扩展命令时先决定“哪一层应拥有这条规则”。命令定义负责语义、校验、目标评分与选择执行后端;CommandSystem 负责 Pawn 上的接受、队列、取消、状态和终结结果;执行定义负责将一条已接受的精确命令路由到 StateTree、Ability、Behavior Tree 或项目运行时。不要让执行后端重新维护命令队列,也不要让 UI 或 Tactical Assignment 绕过命令级校验。
相关文档:系统定位见命令系统,配置字段见命令定义与下发参数,最小接入流程见接入最小命令单位。
先选扩展层级
需求 | 首选位置 | 例子 | 不应放在哪里 |
|---|---|---|---|
一份稳定、可编辑的命令配置 | | Move、Interact、Heal。 | 不要为每个固定配置直接写一套裸 Definition。 |
同一入口的多个稳定变体 | | Attack 的近战、远程、技能变体。 | 不要用 DebugName 当运行时身份,或把每个变体复制成互不关联资产。 |
配置要按执行 Pawn、装备、职业或状态动态计算 | | 同一 Attack 根据武器返回不同 Range 与后端。 | 不要在 UI 或执行层偷偷重写命令语义。 |
目标是否合法、单位是否能执行 | | 眩晕时禁止施法、不能治疗敌人。 | 不要只靠按钮禁用或 Tactical Filter。 |
自动目标/战术分配的偏好 | | 治疗优先低血量近距离友军。 | 不要把候选收集塞到评分函数。 |
已接受命令怎样真正运行 | | 进入 StateTree、启动 Ability、请求 Behavior Tree 任务。 | 不要让 CommandSystem 直接依赖某个具体 AI 框架。 |
何时直接继承 UGAIS_CommandDefinition
Simple 与 MultiVariant 已覆盖“静态配置 + 少量稳定变体”的主路径。直接继承抽象基类的理由应是你需要根据 CommandedActor 与 Index 动态选择行为,例如:
- 同一攻击语义依武器在近战、远程和无人机后端间切换;
- 职业、Buff 或资源改变目标类型、标签需求、射程或 UI;
- 项目有自己的目标数据规则、群体落点算法或可执行性约束;
- 同一个 Tactical Intent 需要由不同 Unit 解析为不同的命令片段。
此时仍应保持每个覆写只负责一个阶段。若只是三个固定攻击变体,继续使用 MultiVariant;若只是一个命令的固定数值,继续使用 Simple。这样设计师仍可在资产中读到大部分规则,C++/蓝图覆写只承载真正动态的差异。
UGAIS_CommandDefinition 的可覆写行为
扩展点 | 改变什么 | 边界 |
|---|---|---|
| 执行 Pawn 是否具备资源、状态、职业、标签或项目许可。 | 只判断执行者,不替代具体目标校验。 |
| Actor/位置目标是否满足命令规则。 | 是命令级真源;UI 和 Tactical Filter 只能提前筛选。 |
| 合法目标之间的偏好。 | 分数不让非法目标重新合法;候选收集属于 Source/项目代码。 |
| 群体下发时,为每个 Pawn 计算不同落点。 | 只产生目标位置,不直接驱动移动组件。 |
| 动态 TargetType 与取消策略。 | 发送端必须使用解析后的实际目标契约。 |
| 动态标签需求和成功条件。 | 不要在这里隐藏与 UI 无法解释的大型决策树。 |
| 按 Pawn 或变体返回执行适配器。 | 返回的对象必须无状态;启动后端后仍由 CommandSystem 管终结。 |
| 动态名称、图标、按钮槽位。 | 只影响显示,不使命令自动有效。 |
| 动态距离语义和评分尺度。 | 不替代导航完成、候选 Source 或最终目标校验。 |
默认 StateTree 执行层应是首选
UGAIS_CommandExecutionDefinition_StateTree 将命令送入 StateTreeStack 的保留 Command 层,并持有完整 FStateTreeReference,可在资产上配置 StateTree 参数和属性覆写。它已经适合大多数 AI 命令:移动、交互、攻击流程、动画协调、等待条件,以及在 StateTree 内启动 Ability。
因此,若 GAS Ability 只是“命令 StateTree 的一个步骤”,保留默认 StateTree 后端通常更合适。它保留了 Command 层的优先级和回退,使命令结束后 Unit/Squad 层 AI 可以自然恢复。Simple 可配置一个 StateTree;MultiVariant 的每个变体都可配置自己的 StateTree,足以让同一命令入口驱动截然不同的行为流程。
默认后端要求:命令接受者是非玩家控制 Pawn、有 AAIController,且 Controller 有 UGAIS_StateTreeStackComponent。如果这些条件不成立,不要试图在 StateTree 执行定义里补救;应为该 Pawn/玩法选合适后端。
何时自定义执行定义
在以下情况继承 UGAIS_CommandExecutionDefinition:
- 项目的既有 Behavior Tree 运行器才是行为任务的真实拥有者;
- 命令应直接启动并等待一个 GAS Ability 的完成/取消;
- 动画、交互、载具或网络动作系统拥有独立的异步生命周期;
- 玩家控制 Pawn 要响应命令,但不符合内置 AI StateTree 后端的上下文要求。
自定义后端的责任只有两件:StartExecution 建立这一次精确命令的路由,CancelExecution 释放仍属于它的外部状态。异步完成时,通过 Context/CommandSystem 回报成功、失败或取消。返回 false 表示后端没有接受启动;如果已建立异步路由,就必须在终结时回报,而不能让 CommandSystem 永远等待。
以两种常见后端为例:
后端 | 适配器应做什么 | 常见错误 |
|---|---|---|
Behavior Tree | 请求项目的 BT 任务/子树执行,并保留能回报本次命令的精确身份。 | 只启动 Task,不把 Task 成功/失败回报给 CommandSystem。 |
GAS Ability | 激活指定 Ability,订阅它的成功、失败和取消,映射为命令终结结果。 | 在取消旧命令时误取消新命令激活的 Ability。 |
精确执行身份与取消边界
CommandSystem 为每次已接受命令创建不透明执行身份。后端在完成或取消时必须针对 Context 所代表的那一次执行,而不是只凭“同一个 Definition”或“当前正在攻击”判断。这一点在快速替换、前插和队列推进时尤为重要:旧命令可能已经被取消,新命令使用相同 Definition 却是另一条执行。
安全规则是:开始时记录后端所拥有的精确执行;完成时仅回报仍匹配的执行;取消时仅释放该执行拥有的任务、Ability、StateTree 路由或视觉状态。CommandSystem 会先使旧身份失效,因此迟到回调不会终结后来命令;适配器仍应主动解除自己的订阅,避免资源泄漏。
排错顺序
- 确认 CommandSystem 位于 Pawn,且权威端实际收到请求。
- 检查 Definition、Index、TargetType 与
FGAIS_CommandData是否一致。 - 检查
CanObeyCommand与IsValidTarget的错误标签。 - 检查
GetExecutionDefinition是否为该 Pawn/Index 返回有效适配器。 - 使用 StateTree 后端时,检查非玩家控制 Pawn、AAIController、StateTreeStack 与有效 StateTree 引用。
- 自定义后端时,确认 Start 已建立可终结路由,完成/取消回调只作用于精确执行。
- 最后查看 GameplayDebugger 的 Current、Queue、LastResult 与 ReasonTag,而不是只看执行层日志。
