> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/debugging-and-troubleshooting.md).

# 排查角色动作问题

诊断动作流水线问题的最快方法是 `ConvaiActionDebugProbe` ——将其添加到你的 NPC 的 `GameObject`，进入 Play 模式，并观察其计数器实时更新。对于后端确认的运行时动作状态、待处理更新确认以及本地补丁测试，请打开 Action Debug Window（**Convai → Developer → Action Debug Window**）。本页涵盖这两个工具的完整参考、诊断检查清单，以及针对每种常见故障模式的完整故障排查表。

### ConvaiActionDebugProbe

`MonoBehaviour` — `Convai.Runtime.Actions`

菜单路径： `添加组件 → Convai → Debug → Convai Action Debug Probe`

约束： `DisallowMultipleComponent`, `RequireComponent(ConvaiCharacter)`

探针会自动解析 `ConvaiCharacter` 和 `ConvaiActionDispatcher` 来自同一个 `GameObject` 于 `Awake`。两者都会在检查器中显示为只读引用字段，用于确认自动解析成功。

#### Inspector 字段

| 字段                    | 类型                       | 描述                                            |
| --------------------- | ------------------------ | --------------------------------------------- |
| `_character`          | `ConvaiCharacter`        | 自动解析。跟踪来自后端的原始动作批次。                           |
| `_dispatcher`         | `ConvaiActionDispatcher` | 自动解析。跟踪执行生命周期事件。                              |
| `_logToConsole`       | `bool`                   | 启用后，所有探针事件都会打印到控制台。为减少干扰，可在测试时关闭。             |
| `_receivedBatchCount` | `int`                    | 通过以下方式从 Convai 接收到的批次总数： `OnActionsReceived`. |
| `_startedStepCount`   | `int`                    | 调度器已开始执行的步骤总数。                                |
| `_succeededStepCount` | `int`                    | 返回以下结果的步骤总数 `成功`.                             |
| `_failedStepCount`    | `int`                    | 返回以下结果的步骤总数 `失败`, `已取消`，或 `超时`.               |
| `_unhandledStepCount` | `int`                    | 返回以下结果的步骤总数 `未处理`.                            |
| `_abortedBatchCount`  | `int`                    | 被以下策略提前中止的批次数总计： `StopBatch` 失败策略。            |
| `_lastReceivedBatch`  | `string` (文本区域)          | 最近一次从 Convai 接收到的批次的 JSON。                    |
| `_lastStepStarted`    | `string` (文本区域)          | 调度器最近开始执行的步骤摘要。                               |
| `_lastStepSucceeded`  | `string` (文本区域)          | 最近一次成功完成的步骤摘要。                                |
| `_lastUnhandledStep`  | `string` (文本区域)          | 最近一次未处理步骤的摘要。                                 |

#### 上下文菜单操作

在检查器中右键单击探针组件标题以访问：

| 命令         | 效果                                                |
| ---------- | ------------------------------------------------- |
| **注入测试批次** | 提交一个 `移动到` 将命令定向到调度器中第一个已注册对象的指令。无需实时对话即可测试完整流水线。 |
| **重置探针状态** | 将所有计数器重置为 `0` 并清空所有文本字段。请在各次测试之间使用，以保持计数器有意义。     |

#### 控制台日志格式

当 `_logToConsole` 启用后，探针会按以下格式写入控制台：

```
[ConvaiActionDebugProbe] 已接收动作批次 #1: [{"name":"Move To","target":"Extinguisher"}]
[ConvaiActionDebugProbe] 调度器批次已开始。
[ConvaiActionDebugProbe] 步骤已开始 #1: cmd='Move To Extinguisher', def='Move To', target=Object:Extinguisher
[ConvaiActionDebugProbe] 步骤成功 #1: cmd='Move To Extinguisher', def='Move To', target=Object:Extinguisher
[ConvaiActionDebugProbe] 调度器批次已完成。
```

对于失败情况：

```
[ConvaiActionDebugProbe] 步骤失败 #1: cmd='Move To Cupboard', def='<unresolved>', target=None:<none>
[ConvaiActionDebugProbe] 调度器批次已中止 #1。
```

### Action Debug Window

`编辑器窗口` — `Convai.Editor.Actions`

菜单路径： `Convai → Developer → Action Debug Window`

一个用于动作流水线的实时检查器：已渲染的后端配置、验证器诊断、本地命令注入，以及运行时调度事件信息流。该窗口会自动解析一个 `ConvaiCharacter`, `ConvaiActionConfigSource`，以及 `ConvaiActionDispatcher` 在当前打开的场景中；使用 **刷新** 以强制重新解析，并使用 **清除** 来重置事件信息流和运行时诊断状态。

#### 已渲染的后端配置

列出每个已编写的 `ConvaiActionDefinition` 来自 `ConvaiActionConfigSource`，以及 `ConvaiActionConfigValidator` 诊断（错误、警告和信息）以及每个动作的生效失败策略——要么是动作级覆盖，要么是调度器的默认 `失败策略`.

#### 运行时动作状态

仅在 Play 模式下可用。离开 Play 模式后，窗口会显示 `进入 Play 模式以检查后端确认的动作状态、待处理补丁和 ACK 元数据。` 运行后，它会显示：

* 会话标签， `已连接，已就绪` 或 `尚未准备好接收运行时动作更新`.
* 一个只读的后端确认快照：当前动作、对象、角色、注意对象、活动定义数量以及可执行目录数量。
* 每个待处理的运行时更新，以及它们的更新 ID、变更类型（`配置`, `注意`，或 `配置 + 注意`），确认状态（`等待 ACK` 或 `已收到 ACK（<status>）`），以及自发送以来经过的秒数。
* 该窗口观察到的最近一次动作更新确认，或 `本窗口未观察到。` 如果尚未到达任何确认。

运行时动作状态由后端确认：在 Convai 返回确认之前，更新会一直保持待处理状态，而成功的确认会按发送顺序提交。错误状态、格式错误或不匹配的确认元数据，或 30 秒超时，都会在不重试的情况下丢弃待处理变更，并且控制台会记录 `[<character name>] 运行时动作变更已丢弃 update_id=<id> reason=<reasonCode>`。断开连接也会丢弃所有待处理变更且不重试，但这是静默进行的——不会记录这条消息。如果确认的 action-generation-strategy 状态为 `requires_reconnect`，控制台还会记录 `[<character name>] 运行时动作更新 ACK 需要重新连接；未执行自动重连（update_id=<id>）` ——SDK 会显示此状态，但不会自动重连。参见 [在运行时更新角色动作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/update-actions-at-runtime.md) 以了解完整的确认模型及其底层 `ConvaiActionConfigPatch` API。

#### 运行时补丁合成器

构建并发送一个 `ConvaiActionConfigPatch` 到实时会话中，映射到中描述的省略与空语义。 [在运行时更新角色动作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/update-actions-at-runtime.md): `未勾选字段 = 省略/保留。已勾选但无值的字段 = 显式清空。只有在匹配且成功的后端 ACK 之后，状态才会被确认更改。` 切换项涵盖动作替换（每行一个动作）、对象替换、角色替换、嵌套 `action_config` attention，以及一个顶层注意覆盖项，当两者都包含时它会生效。设置 **反应** 以及一个可选的 **更新 ID** ——留空可生成一个 action-debug ID。

| Button  | 效果                                             |
| ------- | ---------------------------------------------- |
| `加载已确认` | 将该角色当前已确认的动作配置加载到草稿中，并勾选所有字段。                  |
| `重置草稿`  | 将草稿清空并恢复为全未勾选状态。                               |
| `预览`    | 在本地验证草稿，并在不发送任何内容的情况下显示预测得到的动作配置。              |
| `发送补丁`  | 发送该补丁。仅在角色已连接（`IsInConversation`）且至少包含一个字段时可用。 |

#### 本地注入与预设

**本地注入** 仿照 `ConvaiActionDebugProbe`的测试注入：输入动作名称和目标/参数，然后选择 **注入** 或 **注入 → 第一个已编写对象** 以直接提交命令到 `ConvaiActionDispatcher`，绕过 Convai。每个已编写动作名称也都会列出一个按钮，方便对第一个已注册对象进行一键注入。

**预设** 当项目注册了一个 `IConvaiActionDebugPresetProvider`时会出现。每个提供者都可以公开一个 **应用 \[provider] 模板** 按钮（仅编辑模式——将生成的 `ConvaiActionDefinition` 条目写入到 `ConvaiActionConfigSource`，在匹配的定义上保留现有的执行器和调度调优字段），并提供命名的注入预设以便一键测试。

#### 运行时信息流

最近 80 个事件的滚动日志：接收的批次、步骤开始/完成、批次中止、注入的命令、应用的模板、排队中的运行时补丁（`运行时补丁已排队`），动作更新确认（`运行时动作 ACK`），以及动作响应过滤器诊断（`动作过滤`）。过滤器诊断条目只报告计数——角色 ID、参与者 ID、接收/接受/拒绝总数以及拒绝原因代码——绝不会包含原始动作载荷，因此在日常调试期间可以安全地保持该信息流启用。

### 诊断检查清单

当动作未执行时，请按顺序使用此检查清单：

{% stepper %}
{% step %}

#### 验证后端正在发送动作

检查 `_receivedBatchCount` 在 Play 模式下说出命令后，检查探针检查器中的计数器。

* **计数器递增** → 后端返回了一个动作批次；继续下一步。
* **计数器保持为 0** → Convai 没有返回动作响应。可能原因：
  * `ConvaiActionConfigSource` 没有动作定义（后端不知道可用动作存在）
  * Convai 后端角色未配置为针对该角色 ID 返回动作
  * 会话未成功连接
    {% endstep %}

{% step %}

#### 验证调度器正在处理该批次

如果 `_receivedBatchCount` 递增，但 `_startedStepCount` 仍为 0：

* `ConvaiActionDispatcher` 可能在 NPC 的 `GameObject`
* 检查调度器是否位于 **同一个 `GameObject`** 与 `ConvaiCharacter`
* 验证检查器中调度器组件已启用（组件名称旁的复选框）
  {% endstep %}

{% step %}

#### 读取步骤失败消息

如果 `_failedStepCount` 递增后，展开 `_lastStepStarted` 并在控制台中查找失败消息。调度器会记录确切原因：

| 控制台消息                         | 原因                    |
| ----------------------------- | --------------------- |
| `未找到适用于 'X' 的本地动作定义`          | 动作名称不匹配——请看下一步        |
| `动作 'X' 缺少有效的执行器`             | 执行器字段为空——请分配执行器组件     |
| `未满足目标要求 'Object'（解析结果：None）` | 后端发送的目标名称与任何已注册对象都不匹配 |
| {% endstep %}                 |                       |

{% step %}

#### 检查动作名称是否不匹配

动作名称匹配时 **不区分大小写** 但 **空格是有区别的**. `移动到` 和 `move to` 会匹配。 `移动到` 和 `MoveTo` 不会。

在 `_lastReceivedBatch`，找到后端发送的准确名称。将其与 `ActionName` 中的字段 `ConvaiActionConfigSource`进行比较。两者必须逐字符完全一致（忽略大小写）。
{% endstep %}

{% step %}

#### 验证组件引用

在 `ConvaiActionConfigSource`，展开每个 **动作定义** 条目：

* **执行器字段为空** → 该步骤会因“缺少有效的执行器”而失败。请将执行器组件引用拖入 Executor 字段。
* **执行器未实现 `IConvaiActionExecutor`** → 该步骤会失败。自定义执行器必须实现该接口。
  {% endstep %}

{% step %}

#### 使用 Inject Test Batch 测试

右键单击 `ConvaiActionDebugProbe` → **注入测试批次**，或者使用 **本地注入** 在 Action Debug Window 中。两者都会直接向调度器提交命令，绕过后端。

* **步骤成功** → 流水线工作正常；问题在于 Convai 返回动作的方式，而不是你的 Unity 设置。
* **步骤失败** → 问题出在本地组件配置（执行器、NavMesh、缺失引用）上。

点击 **重置探针状态** 或 **清除** 在各次测试之间，以保持信息流和计数器易于阅读。
{% endstep %}
{% endstepper %}

### 故障排查表

| 症状                                                                   | 可能原因                                                     | 修复                                                                                   | 验证                                                     |
| -------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------ |
| `_receivedBatchCount` 说出命令后仍保持为 0                                    | `ConvaiActionConfigSource` 缺失或没有动作定义                     | 添加 `ConvaiActionConfigSource` 并至少包含一个动作定义；只有当后端知道已配置动作时才会返回动作                        | 再次说出命令； `_receivedBatchCount` 递增                       |
| `_receivedBatchCount` 递增，但 `_startedStepCount` 保持为 0                 | `ConvaiActionDispatcher` 缺失、已禁用，或位于错误的 `GameObject`      | 将调度器添加到同一个 `GameObject` 与 `ConvaiCharacter`；验证其已启用                                   | `_startedStepCount` 在下一批次中递增                           |
| `_failedStepCount` 递增：“未找到适用于 'X' 的本地动作定义”                           | 后端发送的动作名称与任何 `ActionName` 本地定义都不匹配                       | 打开 `_lastReceivedBatch` 以查看准确名称；在 `ConvaiActionConfigSource`                         | 下一次匹配的批次会递增 `_startedStepCount` 而不是 `_failedStepCount` |
| `_failedStepCount` 递增：“缺少有效的执行器”                                     | `执行器` 中的字段 `ConvaiActionDefinition` 为空                   | 将执行器组件引用拖入 `执行器` 中的字段 `ConvaiActionConfigSource`                                     | 步骤到达 `_startedStepCount` 且执行器的行为开始运行                   |
| A `UnityEventActionExecutor` 动作从未触发其监听器                              | 执行器的 UnityEvent 在检查器中没有连接持久监听器                           | 在执行器的 UnityEvent 字段上连接一个监听器；Convai 的 MCP 动作诊断工具会将其标记为 `ACTION_EVENT_UNWIRED`         | 已连接的监听器会在下次动作执行时运行                                     |
| `_failedStepCount` 递增：“未满足目标要求”                                      | 后端的目标名称与任何已注册对象或角色都不匹配                                   | 打开 `_lastReceivedBatch` 以查看目标名称；验证其是否匹配 `名称` 中的条目 **可动作对象** 或 **可动作角色** （不区分大小写）     | 该步骤解析目标，并且 `_startedStepCount` 递增                      |
| `_unhandledStepCount` 递增                                             | 执行器返回 `未处理` ——执行器拒绝处理此次调用                                | 检查执行器逻辑； `未处理` 表示执行器选择不运行，而不是出了故障                                                    | 执行器返回 `成功` 或 `失败` ，而应在逻辑修正后返回                          |
| `_abortedBatchCount` 递增                                              | 某个步骤失败，并且 `StopBatch` 策略中止了剩余步骤                          | 修复失败的步骤（见上文），或者更改 `失败策略` 设置为 `继续批次` ，如果各步骤彼此独立                                       | `OnBatchCompleted` 触发而不是 `OnBatchAborted` 在下一批次中       |
| NPC 瞬移而不是导航移动                                                        | `TransformMoveToActionExecutor` 正在使用                     | 替换为 `NavMeshMoveToActionExecutor` 或使用你的移动系统的自定义执行器                                   | NPC 会平滑移动到目标，而不是直接瞬移到目标                                |
| NPC 开始移动后又冻结                                                         | `NavMeshMoveToActionExecutor` 代理被卡住，或路径被阻挡               | 烘焙 NavMesh（**窗口 → AI → 导航 → 烘焙**）；验证 NPC 和目标都位于 NavMesh 表面；设置 `超时时间（秒）` 以防止无限阻塞      | NPC 会到达目标并完成步骤，而不是超时                                   |
| NPC 能导航但对象没有被拾取                                                      | `PickUpActionExecutor._mover` 为空                         | 分配一个 `NavMeshMoveToActionExecutor` 引用到 `_mover` 中找到它，位于 `PickUpActionExecutor` 检查器   | 对象会重新设为父级到 `_attachPoint` ，一旦拾取流程完成                    |
| 在检查器中配置了动作，但场景切换后不工作                                                 | 连接时发送的配置现在已过期                                            | 结束会话并重新连接；动作配置只会在连接时发送一次                                                             | 重新连接后，请求的动作会应用新配置                                      |
| 动作在编辑器中可用，但在构建版本中不可用                                                 | 执行器组件未包含在构建中                                             | 验证执行器脚本位于项目的编译范围内；检查是否存在 `[assembly: ...]` 排除项                                       | 构建版本的控制台显示与 `ConvaiActionDebugProbe` 编辑器相同的输出          |
| `DynamicContext.SetCurrentAttentionObject` 调用没有效果                    | 不在活动对话中，或者对象名称不在活动配置中                                    | 仅在以下之后调用 `ConnectAsync` 完成；对象名称必须匹配以下内容中的一个已注册条目： `ConvaiActionConfigSource.Objects` | 后续动作目标解析会反映新的注意对象                                      |
| Action Debug Window 中的待处理运行时更新从不清除                                   | 该更新已被丢弃——ACK 错误、格式错误/不匹配的元数据，或 30 秒超时（或在断开连接时静默丢弃）       | 检查控制台中的 `运行时动作变更已丢弃 update_id=... reason=...`；已丢弃的更新不会重试，请使用新的更新 ID 重新发送             | 待处理条目会消失，Last action-update ACK 会显示新状态                 |
| Action Debug Window 的 Last action-update ACK 显示 `requires_reconnect` | Convai 已应用该更改，但 action-generation-strategy 需要一个新的会话      | 结束会话并重新连接；SDK 不会自动重连                                                                 | 重新连接后，Last action-update ACK 会反映重新应用后的状态               |
| `发送补丁` 在运行时补丁合成器中保持禁用                                                | 角色未连接（`IsInConversation` 是 `false`），或者没有勾选任何 Include 切换项 | 在会话连接后发送；发送前至少勾选一个 Include 切换项                                                       | 一旦连接并勾选至少一个 Include 切换项，该按钮就会启用                        |

### 下一步

{% content-ref url="/pages/4001c6ae3c6d4603942748007a37a67812bb7e9a" %}
[在运行时更新角色动作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/update-actions-at-runtime.md)
{% endcontent-ref %}

{% content-ref url="/pages/0341126fa4c492311dab4fb6aca6d0c64191016b" %}
[角色动作脚本参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/actions-scripting-reference.md)
{% endcontent-ref %}

{% content-ref url="/pages/7f0d213ddc809cfd39ab2bc41492ddf8e54b6c19" %}
[角色动作快速入门](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/quick-start.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/debugging-and-troubleshooting.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
