> 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/dynamic-context/troubleshoot-dynamic-context.md).

# 排查动态上下文问题

修复 Convai Unity SDK 中常见的动态上下文问题，包括更新丢失、响应延迟，以及重置行为未清除所有内容。

大多数在中继器和跟踪器流程中的动态上下文问题，通常来自三类情况之一：在角色进入对话之前就调用了某个方法、某种反应模式产生了意外响应，或者一个 `ConvaiDynamicContextRelay` 无法解析一个 `ConvaiCharacter`。请按照下面的第一线排查清单逐步处理——大多数问题会在前两三步内解决。

### 首要排查

{% stepper %}
{% step %}

#### 检查 Unity Console 中的警告

动态上下文警告会由 `ConvaiCharacter` ——前缀为角色名称——以及由 `ConvaiDynamicContextRelay`记录。打开 Console（**窗口 → 常规 → Console**）并查找提到 `动态上下文` 或 `分配一个 ConvaiCharacter`.

如果你看到警告，请在下面的 [控制台日志参考](#console-log-reference) 表中找到确切消息并按列出的修复方式处理。
{% endstep %}

{% step %}

#### 使用示例调试中心隔离问题

在调试你自己的集成之前，请先确认动态上下文本身是否正常工作。请从 **LipSync 示例** 包管理器导入它并打开其场景——该示例包含一个 **示例调试中心** 并传入一个 **上下文** 抽屉，可将状态、事件和注意对象更新发送到场景的 `ConvaiCharacter` ，而无需连接你自己的 UI。

如果角色通过调试中心能正确响应，那么问题出在你自己的中继器或脚本设置中——而不是动态上下文本身。
{% endstep %}

{% step %}

#### 验证角色引用是否已解析

选中 `ConvaiDynamicContextRelay` 组件位于 Inspector 中。

* **启用自动解析角色：** 确认 `ConvaiDynamicContextRelay` 和 `ConvaiCharacter` 位于 **同一个 GameObject 上**.
* **禁用自动解析角色：** 确认 **Character** 字段已分配引用。

如果两者都无法解析角色，则每次调用都会触发 **已跳过回调** 并记录 `请分配一个 ConvaiCharacter，或启用自动解析角色。`
{% endstep %}

{% step %}

#### 检查角色是否处于对话中

跟踪调用—— `SetState`, `SetStates`, `AddEvent`, `RemoveState`, `重置`, `SetCurrentAttentionObject`，以及 `ClearCurrentAttentionObject` ——会在本地立即进入暂存，即使在对话开始之前也是如此。一旦角色变为就绪，暂存的批次会自动送达 Convai，因此在 `Awake()` 或 `Start()` 中发起的调用无需额外处理。

`Apply()` 是例外：它不会暂存。如果在角色不处于对话中时调用，它会被丢弃，而 Convai 会记录 `无法应用原始动态上下文更新：不在对话中`.
{% endstep %}

{% step %}

#### 检查批处理窗口和反应模式

在跟踪的更改被暂存后，SDK 会等待 `ConvaiCharacter.DynamicContextBatchDelaySeconds` ——默认 0.5 秒——再发送，因此多次快速更改会合并为一次更新。调用 `Flush()` 在 `IConvaiDynamicContext`，或在中继器上启用 **Flush Immediately** ，以在不等待的情况下发送已暂存的更改。

如果在你期望 `Silent` 抑制回复时角色却作出了响应，那么在同一批处理窗口中暂存的另一个更改很可能请求了更强的反应—— `MustRespond` 高于 `自动`，它会压过 `Silent`，并作用于整个批次。
{% endstep %}
{% endstepper %}

### 常见问题

| 症状                                                                      | 可能原因                                                                                                 | 修复方法                                                                              | 验证                                                   |
| ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------- |
| 角色从不引用通过 `SetState`                                                     | 发送的状态 `SetState` 当没有任何变化时，                                                                           | 是无操作 `TryGetStateValue` 首先                                                        | `TryGetStateValue` 在用一个确实不同的值调用后，会返回新值               |
| 在 `Awake()` 或 `Start()` 中发起的调用似乎没有效果                                    | 预期行为——跟踪调用会在本地暂存，并在角色变为就绪后自动刷新                                                                       | 跟踪方法无需任何操作；避免在 `Apply()` 对话开始前调用它，因为它不会暂存                                         | 状态或事件会在对话开始后不久出现在角色的回复中                              |
| `ConvaiDynamicContextRelay` 触发 **已跳过回调** 而不是 **已排队**                    | 没有 `ConvaiCharacter` 已解决—— **Auto Resolve Character** 已禁用且未 **Character** 分配，或者中继器位于错误的 GameObject 上 | 启用 **Auto Resolve Character** 并将中继器放在 NPC 的 GameObject 上，或者明确分配 **Character** 显式地 | **已排队** 触发，并且 Console 中没有 `分配一个 ConvaiCharacter` 警告  |
| **已排队** 触发了，但角色从未引用该更新                                                  | 一个空的状态名称或一个 `null` 值在派发后未通过验证—— **已排队** 只是确认已派发，而不是确认该值已被接受                                          | 检查 Console 中的验证警告；参见 [控制台日志参考](#console-log-reference)                            | 更新出现在角色的上下文中，且未记录验证警告                                |
| 更新后角色没有立即响应                                                             | 该调用请求的反应解析为 `Silent`                                                                                 | 使用 `自动` 或 `MustRespond` ——位于中继器的 **Reaction Mode** 字段上，或作为 `reaction` 参数出现在脚本调用中  | 角色在下一回合中引用该更新（`自动`/`Silent`）或立即响应（`MustRespond`)     |
| `AddEvent` 通过中继器发送的内容不会使用其脚本默认值 `自动`                                    | 中继器总会在每次调用时显式传递自己的 **Reaction Mode** 字段，从而覆盖该方法的脚本默认值                                                | 将中继器的 **Reaction Mode** 字段设为 `自动` 或 `MustRespond` 如果该事件应触发回复                      | 角色反应与中继器配置的 **Reaction Mode**，而不是 `AddEvent`的脚本默认值一致 |
| 尽管调用使用了，角色仍会响应 `Silent`                                                 | 同一批处理窗口中暂存的另一个调用请求了 `自动` 或 `MustRespond` ——一个批次中最强的反应会在整个批次中胜出                                       | 将需要独立反应的调用间隔超过批处理窗口，或在它们之间调用 `Flush()` 之间                                         | 该批次会按你期望的反应发送                                        |
| `Apply()` 似乎没有效果                                                        | `Apply()` 绕过本地跟踪器且不会暂存；在活动对话之外发起的调用会被丢弃并伴随警告                                                         | 使用 `SetState`, `AddEvent`，或其他跟踪方法——它们会自动暂存                                        | 更新会出现在角色的下一次回复中                                      |
| `TryGetStateValue` 返回 `false` 在 `Apply()`                               | `Apply()` 从不更新本地跟踪器                                                                                  | 使用 `SetState` 如果该值必须可通过 `TryGetStateValue`                                        | `TryGetStateValue` 返回 `true` 在切换到 `SetState`         |
| 切换到后，角色仍然引用初始场景事实 `Reset()`                                             | 默认 `Reset()` 只会清除运行时跟踪器——初始动态信息文本、系统提示词事实以及会话内的 LLM 记忆都不会受影响                                         | 调用 `Reset(removeStatic: true)` 以便同时让 Convai 移除该会话的静态初始上下文                         | 角色不再引用仅存在于静态初始上下文中的事实                                |
| 无法在同一个 GameObject 上再添加第二个 `ConvaiDynamicContextRelay` 到同一个 GameObject 上 | `[DisallowMultipleComponent]` 限制                                                                     | 将额外的中继器放到子 GameObject 上，禁用 **Auto Resolve Character**，并分配 **Character** 显式地       | 每个中继器都在其分配的角色上独立运行                                   |

### `Apply()` 丢弃了我的更新

`Apply()` 是唯一一个不会暂存的 Dynamic Context 入口点。与 `SetState`, `AddEvent`以及其他跟踪方法不同，在角色不处于活动对话中时发起的调用会立即被丢弃——Convai 会记录 `无法应用原始动态上下文更新：不在对话中` ，并且不会在对话开始后将更新排队等待传递。

{% hint style="warning" %}
使用 `Apply()` 仅适用于高级情况：外部构造上下文文本，或将上下文更新与 action-config 补丁合并。对于任何可能在对话开始前运行的内容，请使用 `SetState`, `AddEvent`，或其他跟踪方法——它们会自动暂存。
{% endhint %}

`Apply()` 也会完全绕过本地跟踪器：通过 `Apply()` 发送的值不会更新 `TryGetStateValue` 可读取的状态。请参见 [`应用`](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/dynamic-context-scripting-api.md#apply) 脚本 API 参考中的完整验证警告列表。

### `Reset()` 将事实保留在原位

调用 `Reset()` 不带参数调用只会清除运行时 Dynamic Context 跟踪器——也就是所有已跟踪的状态和事件。它不会影响角色知识的另外三种来源：

* **初始动态信息文本**，在连接时一次性通过 `ConvaiCharacter`.
* **系统提示词事实** 配置在 Convai 仪表板上。
* **会话内 LLM 记忆** 由模型在各轮对话之间保留。

调用 `Reset(removeStatic: true)` 以便同时让 Convai 移除当前会话中角色的静态初始动态上下文。系统提示词事实和会话内记忆仍然不受影响——没有任何运行时调用会清除这两者。参见 [连接时的静态上下文](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/static-context-at-connection-time.md) 以了解静态初始上下文是如何配置的。

### 角色不响应

以下决策树涵盖了看似没有效果的上下文更新的全部故障排查范围。

```mermaid
flowchart TD
    A[角色未对上下文更新作出响应] --> B{哪个入口点？}
    B -- ConvaiDynamicContextRelay --> C{On Queued 是否触发？}
    C -- 否，触发了 On Skipped --> D[检查 Console 中的\nAssign a ConvaiCharacter 警告]
    C -- 是 --> E{哪个方法？}
    B -- IConvaiDynamicContext 脚本 --> E
    E -- Apply --> F{是否处于活动对话中？}
    F -- 否 --> G[因警告被丢弃\n改用 SetState 或 AddEvent]
    F -- 是 --> H{此批次的反应模式？}
    E -- SetState / AddEvent / 等等 --> H
    H -- Silent --> I[预期：不会立即响应\n检查同一批次中是否有更强的反应]
    H -- Auto 或 MustRespond --> J{更新是否送达 Convai？}
    J -- 是 --> K[检查角色系统提示词\n和仪表板配置]
    J -- 不确定 --> L[使用示例调试中心\n独立验证传递是否成功]
```

### 控制台日志参考

在动态上下文操作期间，以下消息会出现在 Unity Console 中。

| Message                            | 来源                                                                        | 含义                                                                                        | 修复方法                                                                                        | 验证                                        |
| ---------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------- |
| `请分配一个 ConvaiCharacter，或启用自动解析角色。` | `ConvaiDynamicContextRelay`                                               | 没有 `ConvaiCharacter` 已为本次调用解析。                                                            | 启用 **Auto Resolve Character** 并将中继器放在角色的 GameObject 上，或者分配 **Character** 时。                 | 警告不再出现，并且 `已排队` 触发而不是 `已跳过回调`.            |
| `动态上下文状态名称不能为空`                    | `ConvaiCharacter.DynamicContext` — `SetState`, `SetStates`, `RemoveState` | 状态名称为空或仅为空白字符。                                                                            | 传入一个非空且不含空白字符的状态名称。                                                                         | 调用不再记录警告，并且状态会出现在角色的上下文中。                 |
| `动态上下文状态“{name}”不能使用空值`            | `ConvaiCharacter.DynamicContext` — `SetState`, `SetStates`                | 传入给 `{name}` 是 `null`的值。允许空字符串； `null` 不允许。                                               | 传入空字符串，而不是 `null`，或者提供一个实际值。                                                                | 调用不再记录警告，并且 `{name}` 会更新为预期值。             |
| `无法设置空的动态上下文状态`                    | `ConvaiCharacter.DynamicContext` — `SetStates`                            | 传给 `SetStates` 是 `null` 的字典没有条目。                                                          | 请传入至少包含一个名称/值对的字典。                                                                          | 调用不再记录警告，并且所有传入的状态都会出现在角色的上下文中。           |
| `动态上下文事件文本不能为空`                    | `ConvaiCharacter.DynamicContext` — `AddEvent`                             | 事件文本为空或仅为空白字符。                                                                            | 传入非空的事件文本。                                                                                  | 调用不再记录警告，并且事件行会出现在角色的上下文中。                |
| `动态上下文注意对象不能为空`                    | `ConvaiCharacter.DynamicContext` — `SetCurrentAttentionObject`            | 注意对象参数是 `null`.                                                                           | 将一个 `string` 对象名称或 `ConvaiActionObjectDefinition` 引用，或者调用 `ClearCurrentAttentionObject` 替代。 | 调用不再记录警告，并且角色会引用目标对象。                     |
| `无法应用原始动态上下文更新：不在对话中`              | `ConvaiCharacter.DynamicContext` — `应用`                                   | 当 `应用` 被调用时，角色并不处于活动对话中。                                                                  | 使用 `SetState`, `AddEvent`，或者用于可能在对话开始前发生的更新的其他跟踪方法。                                         | 跟踪方法调用成功，并且在对话就绪后更新会送达角色。                 |
| `{purpose} 的连接尚未就绪`                | `ConvaiCharacter.DynamicContext` ——内部发送路径                                 | 传输层已存在，但在一个已暂存的批次、一个 `重置`，或者一个 `应用` 调用尝试发送时，连接尚未就绪。 `{purpose}` 用于说明正在发送的内容，例如 `动态上下文批次`. | 在依赖即时传递之前，确认角色已完全连接（`IsInConversation`）；待连接稳定后重试。                                           | 该消息不再出现，而批次、重置或 `应用` 调用会在下一次尝试时送达 Convai。 |

### 场景元数据未发送（已在 SDK 4.3.0 中修复）

{% hint style="info" %}
SDK 4.3.0 修复了一个问题：待处理的场景元数据可能无法送达 Convai——CHANGELOG 将其记录为“已修复待处理的场景元数据未被刷新。”如果你的项目使用的是 SDK 4.3.0 或更高版本，这不是一个当前症状。如果场景元数据仍然看起来没有送达角色，请在将其视为新问题之前确认 SDK 包版本。
{% endhint %}

### 下一步

{% content-ref url="/pages/743bcc7de155496cbbf02a52a5577aee99f28aab" %}
[中继组件参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/relay-component-reference.md)
{% endcontent-ref %}

{% content-ref url="/pages/5c3f9bcc544ac6f441fe54139ac1c670eeb5c958" %}
[动态上下文脚本 API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/dynamic-context-scripting-api.md)
{% endcontent-ref %}

{% content-ref url="/pages/bb1aef3496a2be08987c770aa7b8072e7d8c5cd6" %}
[同步行为与时序](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/sync-behavior-and-timing.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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/troubleshoot-dynamic-context.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
