命令扩展点

GAIS_Cover
YuewuDev

作者

YuewuDev

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

目录

命令扩展点

扩展命令时先决定“哪一层应拥有这条规则”。命令定义负责语义、校验、目标评分与选择执行后端;CommandSystem 负责 Pawn 上的接受、队列、取消、状态和终结结果;执行定义负责将一条已接受的精确命令路由到 StateTree、Ability、Behavior Tree 或项目运行时。不要让执行后端重新维护命令队列,也不要让 UI 或 Tactical Assignment 绕过命令级校验。

相关文档:系统定位见命令系统,配置字段见命令定义与下发参数,最小接入流程见接入最小命令单位。

先选扩展层级

需求

首选位置

例子

不应放在哪里

一份稳定、可编辑的命令配置

UGAIS_SimpleCommandDefinition Blueprint/C++ 子类。

Move、Interact、Heal。

不要为每个固定配置直接写一套裸 Definition。

同一入口的多个稳定变体

UGAIS_MultiVariantCommandDefinition 的 Variants。

Attack 的近战、远程、技能变体。

不要用 DebugName 当运行时身份,或把每个变体复制成互不关联资产。

配置要按执行 Pawn、装备、职业或状态动态计算

UGAIS_CommandDefinition 子类和动态片段覆写。

同一 Attack 根据武器返回不同 Range 与后端。

不要在 UI 或执行层偷偷重写命令语义。

目标是否合法、单位是否能执行

CanObeyCommand、IsValidTarget。

眩晕时禁止施法、不能治疗敌人。

不要只靠按钮禁用或 Tactical Filter。

自动目标/战术分配的偏好

GetTargetScore、Range 相关覆写。

治疗优先低血量近距离友军。

不要把候选收集塞到评分函数。

已接受命令怎样真正运行

UGAIS_CommandExecutionDefinition。

进入 StateTree、启动 Ability、请求 Behavior Tree 任务。

不要让 CommandSystem 直接依赖某个具体 AI 框架。

何时直接继承 UGAIS_CommandDefinition

Simple 与 MultiVariant 已覆盖“静态配置 + 少量稳定变体”的主路径。直接继承抽象基类的理由应是你需要根据 CommandedActor 与 Index 动态选择行为,例如:

  • 同一攻击语义依武器在近战、远程和无人机后端间切换;
  • 职业、Buff 或资源改变目标类型、标签需求、射程或 UI;
  • 项目有自己的目标数据规则、群体落点算法或可执行性约束;
  • 同一个 Tactical Intent 需要由不同 Unit 解析为不同的命令片段。

此时仍应保持每个覆写只负责一个阶段。若只是三个固定攻击变体,继续使用 MultiVariant;若只是一个命令的固定数值,继续使用 Simple。这样设计师仍可在资产中读到大部分规则,C++/蓝图覆写只承载真正动态的差异。

UGAIS_CommandDefinition 的可覆写行为

扩展点

改变什么

边界

CanObeyCommand

执行 Pawn 是否具备资源、状态、职业、标签或项目许可。

只判断执行者,不替代具体目标校验。

IsValidTarget

Actor/位置目标是否满足命令规则。

是命令级真源;UI 和 Tactical Filter 只能提前筛选。

GetTargetScore

合法目标之间的偏好。

分数不让非法目标重新合法;候选收集属于 Source/项目代码。

CreateIndividualTargetLocations / IsCreatingIndividualTargetLocations

群体下发时,为每个 Pawn 计算不同落点。

只产生目标位置,不直接驱动移动组件。

GetCommonFragment

动态 TargetType 与取消策略。

发送端必须使用解析后的实际目标契约。

GetRequirementFragment

动态标签需求和成功条件。

不要在这里隐藏与 UI 无法解释的大型决策树。

GetExecutionDefinition

按 Pawn 或变体返回执行适配器。

返回的对象必须无状态;启动后端后仍由 CommandSystem 管终结。

GetDisplayFragment

动态名称、图标、按钮槽位。

只影响显示,不使命令自动有效。

GetRequiredRange / GetAcquisitionRadius

动态距离语义和评分尺度。

不替代导航完成、候选 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 会先使旧身份失效,因此迟到回调不会终结后来命令;适配器仍应主动解除自己的订阅,避免资源泄漏。

排错顺序

  1. 确认 CommandSystem 位于 Pawn,且权威端实际收到请求。
  2. 检查 Definition、Index、TargetType 与 FGAIS_CommandData 是否一致。
  3. 检查 CanObeyCommand 与 IsValidTarget 的错误标签。
  4. 检查 GetExecutionDefinition 是否为该 Pawn/Index 返回有效适配器。
  5. 使用 StateTree 后端时,检查非玩家控制 Pawn、AAIController、StateTreeStack 与有效 StateTree 引用。
  6. 自定义后端时,确认 Start 已建立可终结路由,完成/取消回调只作用于精确执行。
  7. 最后查看 GameplayDebugger 的 Current、Queue、LastResult 与 ReasonTag,而不是只看执行层日志。