> 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/setting-up-the-narrative-design-manager.md).

# 配置叙事设计管理器

说明如何将叙事设计管理器添加到角色、从 Convai 同步其故事章节，并在 Inspector 中连接每章节事件。

`ConvaiNarrativeDesignManager` 是挂在角色上的永久监听点。它订阅来自 Convai 的章节变更信号，并将其转发到你在 Inspector 中配置的 Unity Events。每个角色一个 Manager 是标准设置；它在场景生命周期内一直存在于角色的 GameObject 上。

### 添加该组件

{% stepper %}
{% step %}

#### 选择角色 GameObject

选择带有你的 `ConvaiCharacter` 组件的 GameObject。如果两个组件都在同一个 GameObject 上，Manager 会自动检测该角色。
{% endstep %}

{% step %}

#### 添加该组件

在 Inspector 中，点击 **添加组件** 并导航到 **Convai > Narrative Design Manager**.

该 **Character** 字段会自动填充，如果 `ConvaiCharacter` 位于同一个 GameObject 上。如果不是，请手动将你的角色拖入该字段。

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FFwSbVyP7YFCNjTUn0dCE%2Fimage.png?alt=media&amp;token=709232fe-2eb5-4a09-adc8-8aad87697595" alt="ConvaiNarrativeDesignManager added to the character GameObject with Character field auto-populated"><figcaption><p>角色 GameObject 上的 ConvaiNarrativeDesignManager。</p></figcaption></figure>
{% endstep %}

{% step %}

#### 与后端同步

点击 **与后端同步** Inspector 中的按钮。Manager 会调用 `FetchAndSyncFromBackend()`，它会从 Convai 仪表板获取你的角色章节并填充 **Narrative Sections** 列表。

只有当仪表板上的章节列表发生变化时，你才需要执行此操作。章节 ID 和 Unity Event 的绑定会保留在场景文件中，跨会话持续存在。

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FSoEbWhHxS9UEKDDexnFL%2Fimage.png?alt=media&amp;token=7b96dacd-5703-4119-89c8-2124b4f2ad66" alt="Narrative Sections list populated after Sync with Backend"><figcaption><p>成功同步后的 Narrative Sections 列表。</p></figcaption></figure>
{% endstep %}
{% endstepper %}

```mermaid
flowchart TD
    A[点击与后端同步] --> B[FetchSectionsAsync]
    B --> C{成功？}
    C -- 是 --> D[SyncSectionConfigs]
    D --> E[更新 _sectionConfigs 列表]
    E --> F[OnSectionsSynced.Invoke]
    C -- 否 --> G[_lastFetchError 被设置]
    G --> H[错误显示在 Inspector 中]
```

### 同步状态

该 **同步状态** Inspector 中的标题会显示上一次获取操作的当前状态。所有字段均为只读。

| 字段             | 说明                                     |
| -------------- | -------------------------------------- |
| **正在获取**       | `true` 在获取操作进行时。此时同步按钮会被禁用。            |
| **上次同步时间**     | 上次成功同步的时间戳（格式： `yyyy-MM-dd HH:mm:ss`). |
| **上次同步的角色 ID** | 上一次成功同步所使用的角色 ID。用于验证是否配置了正确的角色。       |
| **上次获取错误**     | 最近一次失败获取的错误消息（如果有）。如果上次获取成功，则为空。       |

{% hint style="warning" %}
如果 **上次获取错误** 不为空，最常见的原因是缺少或无效的 API 密钥——请参见 [配置 API 密钥](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/getting-started/configure-api-key.md) 或者在该角色 ID 为空的 `ConvaiCharacter` 组件。
{% endhint %}

同步结果也会通过 `OnSectionsSynced` 事件（请参见下方的全局事件）。该 `SectionSyncResult` 它携带的信息会准确告诉你发生了什么变化：

| 字段                    | 说明                  |
| --------------------- | ------------------- |
| `SectionsAdded`       | 本地列表中新添加的章节（之前未同步）。 |
| `SectionsUpdated`     | 在仪表板上名称发生变化的章节。     |
| `SectionsOrphaned`    | 自上次同步以来已从仪表板移除的章节。  |
| `SectionsReactivated` | 曾经孤立但已在仪表板上恢复的章节。   |

### 叙事章节

同步后，每个仪表板章节都会作为一条条目显示在 **Narrative Sections** 列表中。每个条目都是一个 `UnitySectionEventConfig` ，包含以下字段：

| 字段        | 类型            | 说明                                          |
| --------- | ------------- | ------------------------------------------- |
| **章节 ID** | `string` （只读） | 与仪表板上章节匹配的唯一标识符。切勿手动编辑。                     |
| **章节名称**  | `string` （只读） | 来自仪表板的显示名称。如果名称更改，会在下次同步时自动更新。              |
| **是否孤立**  | `bool` （只读）   | `true` 如果该章节在仪表板上已不再存在。孤立章节会显示警告徽标，其事件不会触发。 |
| **章节开始时** | `UnityEvent`  | 当角色过渡 **进入** 此章节时触发。                        |
| **章节结束时** | `UnityEvent`  | 当角色过渡 **离开** 此章节时触发。                        |

#### 连接章节事件

点击 **+** 按钮上的 **章节开始时** 或 **章节结束时** 以添加监听器。你可以调用场景中任何 GameObject 上的任何公共方法——Animator 参数、AudioSource 播放、UI 面板激活等等。

**示例：** 要在角色进入“Access Granted”章节时解锁一扇门，请拖动门的 `DoorController` 组件拖到监听器字段中，并选择 `DoorController.Unlock`.

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FdskQJcKoJwimtigck5zr%2Fimage.png?alt=media&amp;token=7b28b6da-6bde-48de-a72d-59e6e7247eeb" alt="On Section Start Unity Event wired to a DoorController Unlock method"><figcaption><p>“On Section Start” 绑定到 DoorController 组件。</p></figcaption></figure>

#### 孤立章节

当某个章节从仪表板中删除，但仍存在于你的本地列表中时，它就会变成孤立章节。孤立条目会被保留，这样你就不会丢失 Unity Event 绑定。它们的 `OnSectionStart` 和 `OnSectionEnd` 事件在运行时永远不会触发。如果你在仪表板上恢复了该章节，请点击 **与后端同步** 以重新激活它。

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FHcYSpYUOrvvDNjegzaBP%2Fimage.png?alt=media&amp;token=19160d1a-ac40-47cf-b44c-123c5370c874" alt="Inspector showing an orphaned section entry with a warning badge"><figcaption><p>Narrative Sections 列表中的一个孤立章节条目。</p></figcaption></figure>

{% hint style="danger" %}
**清除所有章节** 会永久移除所有 `UnitySectionEventConfig` 条目，包括所有 `OnSectionStart` / `OnSectionEnd` 绑定。此操作无法撤销。仅在切换到其他角色且不再需要现有绑定时使用。对应的运行时调用是 `ClearAllSectionConfigs()`.
{% endhint %}

### 全局事件

该 **事件** 折叠区域提供三个全局 Unity Events，无论当前激活的是哪一个具体章节，它们都会触发。

| 事件                      | 签名                                 | 触发时机                                                                                       |
| ----------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------ |
| `OnAnySectionChanged`   | `UnityEvent<string>`               | 每当活动章节发生变化时触发。接收新的章节 ID 作为字符串。                                                             |
| `OnSectionDataReceived` | `UnityEvent<NarrativeSectionData>` | 每次章节过渡时触发。携带完整的 `NarrativeSectionData` 负载，包括 `BehaviorTreeCode` 和 `BehaviorTreeConstants`. |
| `OnSectionsSynced`      | `UnityEvent<SectionSyncResult>`    | 在每次成功调用 `FetchAndSyncFromBackend()` 或 `FetchAndSyncFromBackendAsync()`.                    |

`OnAnySectionChanged` 之后触发，适用于需要反映当前故事状态但事先不知道章节 ID 的 UI——例如，每次章节变化时递增的进度指示器。

`OnSectionDataReceived` 提供原始的行为树负载。大多数项目不需要直接使用它；它面向的是会解析 `BehaviorTreeCode` 或 `BehaviorTreeConstants`.

### 字段以避免歧义。

#### 角色引用标题

| 字段            | 默认   | 说明                                                                                 |
| ------------- | ---- | ---------------------------------------------------------------------------------- |
| **Character** | 自动检测 | 该 `ConvaiCharacter` （或任何 `IConvaiCharacterAgent`）进行监听。如果留空，会在同一个 GameObject 上自动查找。 |

#### 叙事章节标题

| 字段         | 默认  | 说明                                              |
| ---------- | --- | ----------------------------------------------- |
| **章节配置**   | 空   | 条目列表。由 `UnitySectionEventConfig` 填充。 **与后端同步**. |
| **活动章节数量** | 已计算 | 非孤立条目的数量（只读，显示在 Inspector 标题中）。                 |
| **孤立章节数量** | 已计算 | 孤立条目的数量（只读，显示在 Inspector 标题中）。                  |

#### 模板键标题

| 字段      | 默认 | 说明                                                                                                                                                                                         |
| ------- | -- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **模板键** | 空  | 条目列表。由 `UnityTemplateKeyConfig` 条目（键/值对）。请参见 [配置叙事模板键](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/narrative-design/template-keys-dynamic-narrative-variables.md) 以获取完整文档。 |

#### 同步状态标题

| 字段             | 默认      | 说明                  |
| -------------- | ------- | ------------------- |
| **正在获取**       | `false` | 只读。 `true` 在主动获取期间。 |
| **上次同步时间**     | 空       | 只读。上次成功同步的时间戳。      |
| **上次同步的角色 ID** | 空       | 只读。上次同步中使用的角色 ID。   |
| **上次获取错误**     | 空       | 只读。上次错误消息；成功时为空。    |

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FLWXVaqBRtYqinjDXnRQW%2Fimage.png?alt=media&amp;token=1e72b484-06f8-4bc0-a6d7-0d2df44f7e0d" alt="ConvaiNarrativeDesignManager Inspector showing all header sections"><figcaption><p>ConvaiNarrativeDesignManager 的完整 Inspector 视图。</p></figcaption></figure>

### 下一步

{% 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/630c1743293b81e62f2237b571dcf928c0d73285" %}
[配置叙事模板键](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/narrative-design/template-keys-dynamic-narrative-variables.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/narrative-design/setting-up-the-narrative-design-manager.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.
