> 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/narrative-design/troubleshooting-and-diagnostics.md).

# 排查叙事设计问题

使用内置验证与诊断工具，解决触发器状态失败、Inspector 配置错误、获取错误和队列超时问题。

大多数叙事设计问题都属于三类之一：触发器未触发，节事件未响应，或后端获取失败。本页将涵盖这三类问题，先从位于 `ConvaiNarrativeDesignTrigger` 并逐步排查最常见的 Inspector 配置错误。

### 第一线排查

当某个功能不工作时，请先按照这份检查清单排查，再去查看具体症状。大多数问题会在第 2 或第 3 步解决。

{% stepper %}
{% step %}

#### 检查触发器上的 CurrentStatus

选择 `ConvaiNarrativeDesignTrigger` Inspector 中的 GameObject。 **当前状态** 显示在组件顶部。除 `就绪` 之外的任何值都会立即告诉你触发器正在等待什么——请参见下方的 TriggerStatus 参考表以了解解决方法。
{% endstep %}

{% step %}

#### 启用诊断并复现问题

在 Trigger 组件中，启用 **启用诊断**。点击 Play 并重复应当触发该触发器的操作。每一次状态转换——进入/退出区域、队列开始、角色就绪检测、发送触发器——都会记录到 Console。按从上到下阅读日志序列，找出链条断开的地方。

```csharp
// 或从代码中启用
trigger.SetDiagnosticsEnabled(true);
```

{% endstep %}

{% step %}

#### 验证角色 ID 和 API 密钥

打开 **Edit > Project Settings > Convai SDK** 并确认 API 密钥已存在。选择角色的 GameObject，并确认 **Character ID** 字段在 `ConvaiCharacter` 中不为空。如果任一项缺失，从触发器的角度看，获取操作和会话连接都会静默失败。
{% endstep %}

{% step %}

#### 输出完整触发器状态

调用 `PrintDiagnostics()` ，或在 Play 模式下点击组件上显示的 **Invoke** / **Reset** 按钮。该输出会一次显示所有字段，从而让不匹配一目了然：

```csharp
trigger.PrintDiagnostics();
```

{% endstep %}

{% step %}

#### 运行 ValidateConfiguration

```csharp
if (!trigger.ValidateConfiguration())
{
    foreach (string warning in trigger.ValidationWarnings)
        Debug.LogWarning($"触发器验证：{warning}");
}
```

或者在 Inspector 中启用 **启动时验证** ，这样它会在每次 Play 会话开始时自动运行。
{% endstep %}
{% endstepper %}

### TriggerStatus 参考

`ConvaiNarrativeDesignTrigger.CurrentStatus` 始终报告触发器的当前状态。使用它来理解为什么触发器没有触发。

| 状态                          | 原因                                    | 解决方法                                               |
| --------------------------- | ------------------------------------- | -------------------------------------------------- |
| `就绪`                        | 正常——正在等待激活条件。                         | 无需处理。                                              |
| `AlreadyFired`              | `TriggerOnce` 已启用且触发器已触发。             | 调用 `ResetTrigger()` 以重新武装它，或禁用 **仅触发一次** 检查器中进行配置。 |
| `QueuedWaitingForCharacter` | 触发器已被接受，但角色尚未进入活动会话。                  | 等待会话打开。触发器会自动触发。调用 `CancelQueuedTrigger()` 以中止队列。  |
| `ConfigurationError`        | `ValidateConfiguration()` 检测到一个或多个问题。 | 读取 `ValidationWarnings` （参见以编程方式验证配置）并修复每个问题。      |
| `Disabled`                  | 组件或其父级 GameObject 已禁用。                | 启用该组件或 GameObject。                                 |

### 常见问题

| 症状                              | 可能原因                           | 修复方法                                                                                                                                             |
| ------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| 在以下操作后，Sections 列表为空： **与后端同步** | API 密钥缺失或无效                    | 验证你的 API 密钥——参见 [配置 API 密钥](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/getting-started/configure-api-key.md)；检查 **最后一次获取错误** 在 Manager 上 |
| 在以下操作后，Sections 列表为空： **与后端同步** | 未设置角色 ID                       | 设置 **Character ID** 在 `ConvaiCharacter` 组件                                                                                                       |
| `OnTriggerActivated` 已触发，但节从未变化 | 触发器名称与仪表板端点不完全匹配（区分大小写）        | 点击 **获取** 在 Trigger 上，从下拉菜单中重新选择正确的触发器                                                                                                           |
| `OnSectionStart` 尽管节已变化，却从未触发   | 本地节 ID 与仪表板不同步                 | 点击 **与后端同步** 在 Manager 上；如果仍然有问题，请调用 `ClearAllSectionConfigs()` 并重新同步                                                                            |
| `OnPlayerEnterZone` 从未触发（碰撞模式）  | **Is Trigger** 在 Collider 上被禁用 | 启用 **Is Trigger** 在 Collider 组件上                                                                                                                 |
| `OnPlayerEnterZone` 从未触发（碰撞模式）  | 否 `Rigidbody` 在任一对象上           | 添加一个 `Rigidbody` 到触发器 GameObject 或玩家                                                                                                             |
| `OnPlayerEnterZone` 从未触发（碰撞模式）  | 玩家 GameObject 的标签未设置为 `玩家`     | 将标签设置为 `玩家` 在 Inspector 中                                                                                                                        |
| 错误的对象激活了触发器                     | **Player Layer** 掩码设置为 `无` (0) | 设置 **Player Layer** 为你玩家所在的层                                                                                                                     |
| 玩家标签未被识别                        | Unity 的 Tag Manager 中未定义该标签    | 在以下位置添加该标签 **编辑 > 项目设置 > Tags and Layers**                                                                                                       |
| “找到多个 ConvaiCharacters” 警告      | `自动查找角色` 无法消除歧义                | 在中明确分配目标角色 **角色** 字段                                                                                                                             |
| Section 显示 **孤立的** 标记           | 本地同步后，仪表板中的 Section 已删除        | 如果是有意的：手动删除条目。如果是误删：在仪表板中恢复，然后点击 **与后端同步**                                                                                                       |
| 模板键对角色对话没有影响                    | 键名大小写与仪表板占位符不匹配                | 请精确比较键： `{playerName}` 在仪表板中 → 键 `playerName`，而不是 `PlayerName`                                                                                   |

### 启用诊断

`ConvaiNarrativeDesignTrigger` 内置了诊断日志记录器。可在 Inspector 中或从代码中启用它：

```csharp
trigger.SetDiagnosticsEnabled(true);
```

启用诊断后，每一次状态转换——进入/退出区域、队列开始、角色就绪检测、发送触发器——都会通过 `ConvaiLogger.Debug`.

记录到 Console。

```csharp
trigger.PrintDiagnostics();
```

`PrintDiagnostics()` 日志：

```
[ConvaiNarrativeDesignTrigger] === 诊断 ===
  GameObject: TriggerZone_Checkpoint1
  状态：QueuedWaitingForCharacter
  是否已触发：False
  仅触发一次：True
  触发器名称：'CheckpointReached'
  触发器 ID：'a1b2c3d4-...'
  激活模式：Collision
  已分配角色：SafetyInstructor
  角色就绪：False
  玩家在区域内：True
  玩家 Transform：PlayerController
  已排队等待就绪：True
  最后错误：无
  验证警告：0
===========================
```

在 Play 模式下，Inspector 还会显示一个 **Invoke** 按钮（触发 `InvokeTrigger()`）以及一个 **Reset** 按钮（触发 `ResetTrigger()`）可直接在 Inspector 中使用，无需编写任何代码。

### 以编程方式验证配置

```csharp
bool valid = trigger.ValidateConfiguration();

if (!valid)
{
    foreach (string warning in trigger.ValidationWarnings)
        Debug.LogWarning($"触发器验证：{warning}");
}
```

`ValidateConfiguration()` 会执行四项自动检查：

1. **角色引用检查**：验证是否已分配角色，并且是否实现了 `IConvaiCharacterAgent`.
2. **触发器名称检查**：验证至少有一个 **触发器名称** 或 **触发器消息** 非空时。
3. **Collider 检查** （碰撞和基于时间的模式）：验证 `Collider` 存在于同一个 GameObject 上，并且 **Is Trigger** 已启用。
4. **玩家检测检查**：验证 **Player Tag** 已在 Unity 的 Tag Manager 中定义，并在以下情况下发出警告： **Player Layer** 设置为 `无` (0).

启用 **启动时验证** 在 Inspector 中启用此项可在 `Start()` ，以便在 Play 模式一开始就捕获问题。

### 获取失败

如果 `FetchAndSyncFromBackend()` 失败：

1. **最后一次获取错误** 在 Manager Inspector 上显示确切的错误字符串。
2. 调用 `ClearFetchError()` 在解决问题后重置错误显示：

```csharp
narrativeManager.ClearFetchError();
```

常见原因：

| 错误                                                  | 原因                                                                                                                 |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `"API 密钥未配置。请在 Project Settings > Convai SDK 中设置。"` | API 密钥未设置——参见 [配置 API 密钥](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/getting-started/configure-api-key.md) |
| `"需要角色 ID。"`                                        | 上的 Character ID 字段为空 `ConvaiCharacter`                                                                             |
| `"异常：..."`                                          | 网络错误，或 Convai 无法访问                                                                                                 |
| `"未分配角色，或角色没有 ID。"`                                 | Manager 没有角色引用，且自动检测失败                                                                                             |

你也可以在代码中检查 `FetchAndSyncFromBackendAsync()` 的结果：

```csharp
SectionSyncResult result = await narrativeManager.FetchAndSyncFromBackendAsync();
if (!result.Success)
    Debug.LogError($"同步失败：{result.Error}");
```

### 待处理状态

当模板键或触发器在角色会话尚未打开时发送，SDK 会将它们保存在内部队列中。交付是自动的——你无需手动重新发送任何内容。

| 事件        | 会发生什么                                                              |
| --------- | ------------------------------------------------------------------ |
| 会话打开      | `FlushPending()` 会在内部被调用；所有已排队的键和触发器都会按顺序发送。                       |
| 会话断开并重新连接 | `MarkPendingReplayAfterDisconnect()` 会在内部被调用；最新的模板键快照会在下一次连接时重新发送。 |

你可以在场景生命周期中的任何时刻调用 `SetTemplateKey` 或 `InvokeTrigger` ，包括在 `Awake` 中，或者在 Play 模式尚未完全运行之前——SDK 都会在连接准备就绪后正确传递这些值。

### 队列超时

`ConvaiNarrativeDesignTrigger`的 **等待就绪队列** 功能每 0.25 秒轮询一次角色是否就绪。超时时间由 **最大等待时间** （默认： `30` （秒）控制。

当达到超时时， `OnTriggerFailed` 会触发，并显示消息：

```
等待角色就绪超时，已超过 30 秒。
```

在超时前取消已排队的触发器：

```csharp
trigger.CancelQueuedTrigger();
```

{% hint style="warning" %}
设置 **最大等待时间** 移动到 `0` 会完全禁用超时。在会话永远无法连接的构建中（例如由于网络中断），等待协程会一直运行，直到场景卸载。对于正式版本，请始终设置合理的超时时间，并处理 `OnTriggerFailed` 以通知用户或优雅降级。
{% endhint %}

### 控制台日志参考

当 **启用诊断** 开启或运行时发生错误时，会出现以下日志消息。

{% hint style="info" %}
SDK 的日志记录器会自动在每条控制台条目前加上 `[SourceFileName]`，取自记录它的源文件——例如 `[ConvaiNarrativeDesignTrigger]` 或 `[ConvaiNarrativeDesignManager]`。以下消息是该前缀后面的消息正文；在 Console 中搜索消息文本，而不是完整行。通过触发器内部诊断助手记录的仅诊断行还带有第二个内层前缀，即 GameObject 名称，因此这些行显示为 `[ConvaiNarrativeDesignTrigger] [<GameObject name>] <message>`.
{% endhint %}

| 日志消息                                                   | 组件                             | 含义                                                      |
| ------------------------------------------------------ | ------------------------------ | ------------------------------------------------------- |
| `触发器“<name>”已成功在角色“<character>”上调用。`                   | `ConvaiNarrativeDesignTrigger` | 触发器已被接受并成功发送到后端。                                        |
| `触发器“<name>”已排队。正在等待角色就绪（最长 <N> 秒）。`                   | `ConvaiNarrativeDesignTrigger` | 角色会话尚未打开。触发器将在连接时自动触发。                                  |
| `[<GameObject name>] 角色在 <N> 秒后变为就绪，正在发送已排队的触发器`       | `ConvaiNarrativeDesignTrigger` | 会话已打开；延迟的触发器现在正在发送。仅当 **启用诊断** 开启时显示。                   |
| `等待角色就绪超时，已超过 <N> 秒。`                                  | `ConvaiNarrativeDesignTrigger` | `MaxWaitTime` 已耗尽。处理 `OnTriggerFailed` 并增加超时时间，或检查会话连接。 |
| `触发器已触发，且已启用 TriggerOnce。请调用 ResetTrigger() 以允许其再次触发。` | `ConvaiNarrativeDesignTrigger` | `TriggerOnce` 是 `是` 且触发器已触发过。                           |
| `验证：<detail>`                                          | `ConvaiNarrativeDesignTrigger` | 在 Start 时检测到一个配置问题。请阅读详细字符串以查看具体字段。                     |
| `找到多个 ConvaiCharacters（<N>）。无法自动分配。请明确指定一个。`           | `ConvaiNarrativeDesignTrigger` | 自动查找存在歧义。请将正确的角色拖到 **角色** 字段中。                          |
| `节转换：上一个=<id> → 新的=<id>`                               | `ConvaiNarrativeDesignManager` | 收到节转换。如果 `OnSectionStart` 未触发，则该节 ID 不在本地配置列表中——请重新同步。  |
| `同步完成：新增 <N>，更新 <N>，孤立 <N>，重新激活 <N>`                   | `ConvaiNarrativeDesignManager` | 上一次 **与后端同步** 调用的摘要。非零的孤立计数意味着仪表板中的 Section 已被移除。       |
| `获取失败：<error>`                                         | `ConvaiNarrativeDesignManager` | API 密钥、角色 ID 或网络问题。请检查 **最后一次获取错误** 检查器中进行配置。           |

### 触发器未触发

```mermaid
flowchart TD
    A[触发器未触发] --> B[检查 CurrentStatus]
    B --> C{状态？}
    C -- AlreadyFired --> D[调用 ResetTrigger\n或禁用 Trigger Once]
    C -- QueuedWaitingForCharacter --> E[等待会话\n或检查 MaxWaitTime]
    C -- ConfigurationError --> F[阅读 ValidationWarnings\n修复每个问题]
    C -- Disabled --> G[启用组件\n或父级 GameObject]
    C -- Ready --> H{角色已就绪？}
    H -- false --> I{QueueUntilReady？}
    I -- false --> J[启用 Queue Until Ready\n或在触发前等待会话]
    I -- true --> K[触发器已排队\n等待会话打开]
    H -- true --> L{已设置 TriggerName？}
    L -- empty --> M[获取触发器并选择一个\n或从代码中调用 SetTrigger]
    L -- set --> N[检查网络连接\n和后端图配置]
```

使用 `CurrentStatus` 获取瞬时诊断，请启用 `EnableDiagnostics` 以跟踪完整事件链，并使用常见问题表来解决最常见的配置错误。

### 下一步

{% content-ref url="/pages/87ddb3e30dd1b009eb7bf39b583b5a654f486dbb" %}
[配置叙事设计触发器](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/narrative-design/setting-up-narrative-design-triggers.md)
{% endcontent-ref %}

{% content-ref url="/pages/e2aeb655628e9664d3a8c2993eb219a88fcfeef0" %}
[叙事设计脚本参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/narrative-design/scripting-narrative-design.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/narrative-design/troubleshooting-and-diagnostics.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.
