> 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-narrative-design-triggers.md).

# 配置叙事设计触发器

说明如何添加一个叙事设计触发器，通过碰撞、接近、计时或手动信号推进角色的故事。

`ConvaiNarrativeDesignTrigger` 向 Convai 发送一个命名信号，用于将故事图从一个章节推进到下一个章节。将它放在任何 GameObject 上——门口、展品、UI 按钮的事件目标——并选择它应如何激活。叙事触发器不同于 Unity 物理触发器：激活模式控制 *当* 信号何时发送，而不是触发哪种 Unity 物理事件。

### 添加触发器组件

{% stepper %}
{% step %}

#### 创建或选择一个 GameObject

对于基于区域的激活（Collision、Proximity、TimeBased），创建一个空的 GameObject，并将其放置在你希望触发区域位于的场景位置。对于 Manual 激活，你可以将该组件放在任何地方。
{% endstep %}

{% step %}

#### 添加该组件

点击 **添加组件** 并导航到 **Convai > Convai Narrative Design 触发器**.

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FM4Gbj8rb6OhxzB28gA98%2Fimage.png?alt=media&amp;token=7b2f3641-98fd-4c2c-804b-9f1e95653e63" alt="ConvaiNarrativeDesignTrigger added via Add Component in the Unity Inspector"><figcaption><p>将 ConvaiNarrativeDesignTrigger 添加到一个 GameObject。</p></figcaption></figure>
{% endstep %}

{% step %}

#### 分配角色

拖动你的 `ConvaiCharacter` 到 **Character** 字段。如果你将其留空， **Auto Find Character** 会先搜索父级层级结构，然后搜索 `ConvaiManager`的角色列表。如果场景中有多个角色，请显式分配目标。
{% endstep %}

{% step %}

#### 获取并选择一个触发器

点击 **获取** 在 **触发器选择** 部分。SDK 会调用 `NarrativeDesignFetcher.FetchTriggersAsync` 并将该角色在控制台中定义的所有触发器填充到下拉菜单中。

选择你希望此组件发送的触发器。 **触发器名称**, **触发器 ID**，以及 **目标章节** 字段会自动填充。 **触发器消息** 仅作为从 Convai 获取的元数据显示；组件只发送已保存的触发器名称。

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FEqHSckjPlBbbfdgbpdgE%2Fimage.png?alt=media&amp;token=80be2bb4-5692-467c-bda9-3b63bdbe192c" alt="Trigger Selection dropdown showing fetched triggers from the Convai dashboard"><figcaption><p>从 Convai 控制台填充的触发器下拉菜单。</p></figcaption></figure>
{% endstep %}

{% step %}

#### 选择一个激活模式

从下方描述的四种激活模式中选择一种，并配置其设置。
{% endstep %}
{% endstepper %}

### 激活模式

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2FdpxWrkjQHxcgoGSNKgGU%2Fimage.png?alt=media&amp;token=dcaa9022-e321-41d0-8767-667fba499d4a" alt="Activation Settings header in the Inspector showing all four activation mode options"><figcaption><p>带有模式选择器的激活设置标题。</p></figcaption></figure>

#### Collision

默认模式。当带有标签的玩家 GameObject 进入附加在同一 GameObject 上的碰撞体时，触发器会触发。

**要求：**

* 一个 `Collider` 组件位于同一个 GameObject 上，并且具有 **Is Trigger** 已启用。
* 触发器 GameObject 或玩家 GameObject 之一必须具有 `Rigidbody` ，以便 Unity 物理系统生成 `OnTriggerEnter` 回调。

{% hint style="warning" %}
如果 **Is Trigger** 未在碰撞体上启用，或者触发对象和玩家都没有 `Rigidbody`, `OnTriggerEnter` 则永远不会触发。启用 **Validate On Start** 即可在场景运行时自动捕获此问题。
{% endhint %}

**检测设置：**

| 字段       | 默认值        | 说明                            |
| -------- | ---------- | ----------------------------- |
| **玩家标签** | `"Player"` | 只有带有此标签的 GameObject 才会被识别为玩家。 |
| **玩家层**  | 所有图层       | 用于进一步筛选哪些对象算作玩家的层掩码。          |

#### 接近

当玩家与该组件的距离 `Transform` 落入 **接近半径**时，触发器会触发。检查会在 `Update`中每帧运行。场景视图中会绘制一个绿色球体，显示检测半径。

| 字段         | 默认值        | 说明                                |
| ---------- | ---------- | --------------------------------- |
| **接近半径**   | `3`        | 世界单位中的检测半径。                       |
| **玩家标签**   | `"Player"` | 用于标识玩家的标签。                        |
| **自动查找玩家** | `true`     | 如果未分配，则在场景中搜索带有该标签的玩家 GameObject。 |

此模式不需要碰撞体。

#### 基于时间

当玩家在碰撞体区域内停留达到设定时长后，触发器会触发。如果玩家在延迟结束前离开，倒计时将取消，并在下次玩家进入时重新开始。

**要求：** 与 Collision 模式相同的碰撞体设置。

| 字段       | 默认值        | 说明                      |
| -------- | ---------- | ----------------------- |
| **时间延迟** | `0`        | 玩家必须在区域内停留多少秒后，触发器才会触发。 |
| **玩家标签** | `"Player"` | 用于标识玩家的标签。              |

#### 手动

触发器不会自动执行任何操作。调用 `InvokeTrigger()` 或 `TryInvokeTrigger()` 即可从你自己的代码或 Unity 事件中触发它。当激活条件完全由你的游戏逻辑控制时，请使用此模式——例如 UI 按钮、任务完成回调或计分交互。

```csharp
// 从代码触发触发器
narrativeTrigger.InvokeTrigger();

// 静默尝试——如果 TriggerOnce 已经触发，则跳过且不警告
narrativeTrigger.TryInvokeTrigger();
```

### 触发器请求模式

激活模式和触发器请求模式是两个独立设置。激活模式（`Collision`, `接近`, `基于时间`, `手动`）控制 *当* `ConvaiNarrativeDesignTrigger` 是否触发，如上所述。触发器请求模式控制 *什么* 在触发后通过 RTVI 发送给 Convai 的内容。

`ConvaiNarrativeDesignTrigger` 始终使用以下方式发送其配置的触发器 `ConvaiNarrativeTriggerMode.SavedTrigger`。内部会调用 `convaiCharacter.NarrativeDesign.InvokeTrigger(_triggerName)`，它只发送 `trigger_name` 字段。此组件在 Inspector 中没有选项可切换到另外两种触发器请求模式。

在 `ConvaiNarrativeTriggerRequest` （命名空间 `Convai.Runtime.NarrativeDesign`):

| 触发器请求模式  | 字段映射                                  | 上还存在另外两种触发器请求模式                                                                            |
| -------- | ------------------------------------- | ------------------------------------------------------------------------------------------ |
| `已保存触发器` | `trigger_name`                        | `ConvaiNarrativeDesignTrigger` （此组件），或 `IConvaiNarrativeDesign.InvokeTrigger(string)` 从代码中 |
| `内联事件`   | `trigger_message`                     | `IConvaiNarrativeDesign.InvokeEvent(string)` ——仅限代码，无对应 Inspector 选项                       |
| `脚本化语音`  | `trigger_message` （包裹在 `<speak>` 标签中） | `IConvaiNarrativeDesign.InvokeSpeech(string)` ——仅限代码，无对应 Inspector 选项                      |

`内联事件` 和 `脚本化语音` 无法从此组件的 Inspector 中访问。请使用 `InvokeEvent` 来发送 Convai 会自然响应的上下文事件文本，或者 `InvokeSpeech` 让角色准确说出脚本化文本，而不推进叙事图。请参阅 [叙事设计脚本参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/narrative-design/scripting-narrative-design.md) 以获取完整的代码 API。

### 自动恢复设置

这些设置使触发器能够应对常见的运行时情况，例如角色或玩家可能不会立即就绪。

<figure><img src="https://2402152281-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FEtUJA212Zc1S9ACc8T4l%2Fuploads%2F32eKYsxh76KaDYTQLAsv%2Fimage.png?alt=media&amp;token=ad906023-378b-4118-9cc6-c07509d52f94" alt="Auto-Recovery Settings header in the Inspector"><figcaption><p>自动恢复设置标题。</p></figcaption></figure>

| 字段                      | 默认值    | 说明                                                                                                              |
| ----------------------- | ------ | --------------------------------------------------------------------------------------------------------------- |
| **Auto Find Character** | `true` | 先搜索父级层级结构，然后 `ConvaiManager.Characters`。如果只存在一个角色，则自动分配；如果找到多个角色，则记录警告。                                         |
| **自动查找玩家**              | `true` | 先按玩家标签搜索，然后按常见名称列表搜索，再通过 `Camera.main.parent`.                                                                  |
| **等待就绪后排队**             | `true` | 如果角色尚未处于活动对话中（`IsInConversation` 是 `false`），则触发器会进入队列，并在连接建立时自动触发。你无需 `IsInConversation` 在调用 `InvokeTrigger()`. |
| **最大等待时间**              | `30`   | 等待角色就绪的最长秒数。设置为 `0` 即可表示不超时。                                                                                    |
| **场景加载时重置**             | `true` | 调用 `ResetTrigger()` 每当场景加载时都会调用，因此在重新加载的场景中触发器可以再次触发。                                                           |

{% hint style="warning" %}
设置 **最大等待时间** 到 `0` 在会话可能永远不会连接的生产版本中这样做会创建一个无限协程。除非你能明确控制会话生命周期，否则始终设置合理的超时时间。
{% endhint %}

### 控制触发频率

**仅触发一次** （默认 `true`）可防止触发器多次触发。首次成功调用后， `HasTriggered` 会变成 `true`, `CurrentStatus` 会变成 `AlreadyFired`，并且后续所有调用都会返回 `false`.

若要让触发器再次触发，请调用 `ResetTrigger()`:

```csharp
narrativeTrigger.ResetTrigger();
```

`ResetTrigger()` 还会取消任何正在等待角色就绪的排队触发。

若要让触发器在每次激活时都触发，请禁用 **仅触发一次** 在 Inspector 中。

### 事件参考

| 事件                   | 签名                   | 触发时机                     |
| -------------------- | -------------------- | ------------------------ |
| `OnTriggerActivated` | `UnityEvent`         | 触发器已成功发送到后端。             |
| `OnPlayerEnterZone`  | `UnityEvent`         | 玩家进入了碰撞体或接近区域（在触发器触发之前）。 |
| `OnPlayerExitZone`   | `UnityEvent`         | 玩家离开了碰撞体或接近区域。           |
| `OnTriggerFailed`    | `UnityEvent<string>` | 触发器未能触发。字符串参数包含错误消息。     |
| `OnTriggerQueued`    | `UnityEvent`         | 触发器已被接受，但因角色尚未进入对话而被延迟。  |

### 触发器状态

该 `CurrentStatus` 属性会始终跟踪触发器的状态：

```mermaid
stateDiagram-v2
    [*] --> 就绪
    就绪 --> 已触发 : InvokeTrigger() 成功\n(TriggerOnce = true)
    就绪 --> 等待角色排队中 : 调用了 InvokeTrigger()\n角色未就绪\nQueueUntilReady = true
    就绪 --> 配置错误 : ValidateConfiguration() 失败
    等待角色排队中 --> 已触发 : 角色变为就绪
    等待角色排队中 --> 配置错误 : 超过 MaxWaitTime
    已触发 --> 就绪 : ResetTrigger()
    配置错误 --> 就绪 : 修复问题 + ValidateConfiguration()
    就绪 --> 已禁用 : 组件或 GameObject 被禁用
    已禁用 --> 就绪 : 组件或 GameObject 重新启用
```

参见 [叙事设计故障排查](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/narrative-design/troubleshooting-and-diagnostics.md) 以获取每种状态的完整解决指南。

### Inspector 参考

#### 角色引用标题

| 字段                      | 默认值    | 说明                                                                |
| ----------------------- | ------ | ----------------------------------------------------------------- |
| **Character**           | None   | 目标对象 `ConvaiCharacter`。如果留空并且 **Auto Find Character** 已启用，则会自动找到。 |
| **Auto Find Character** | `true` | 如果 Character 字段为空，则搜索层级结构和 ConvaiManager。                         |

#### 触发器选择标题

| 字段         | 默认值 | 说明                                                     |
| ---------- | --- | ------------------------------------------------------ |
| **触发器 ID** | 为空  | 选择后为只读。来自控制台的唯一标识符。                                    |
| **触发器名称**  | 为空  | 此组件触发时发送给 Convai 的已保存触发器名称。                            |
| **触发器消息**  | 为空  | 从 Convai 获取的只读元数据。它不会由 `ConvaiNarrativeDesignTrigger`. |

#### 激活设置标题

| 字段        | 默认值         | 说明                                         |
| --------- | ----------- | ------------------------------------------ |
| **激活模式**  | `Collision` | 触发器如何激活： `Collision`, `接近`, `手动`，或 `基于时间`. |
| **接近半径**  | `3`         | Proximity 模式的检测半径。                         |
| **时间延迟**  | `0`         | TimeBased 模式的倒计时秒数。                        |
| **仅触发一次** | `true`      | 如果启用，则只会触发一次，直到 `ResetTrigger()` 被调用。      |
| **玩家层**   | 所有          | 用于玩家检测的层掩码。                                |
| **玩家标签**  | `"Player"`  | 用于识别玩家 GameObject 的标签。                     |

#### 自动恢复设置标题

| 字段          | 默认值    | 说明                        |
| ----------- | ------ | ------------------------- |
| **自动查找玩家**  | `true` | 如果未检测到带标签的玩家，则在场景中搜索。     |
| **等待就绪后排队** | `true` | 在角色会话打开之前延迟触发器。           |
| **最大等待时间**  | `30`   | 队列的超时时间（秒）。 `0` = 无超时。    |
| **场景加载时重置** | `true` | 重置 `HasTriggered` 于场景加载时。 |

#### 诊断标题

| 字段                    | 默认值     | 说明                                              |
| --------------------- | ------- | ----------------------------------------------- |
| **启用诊断**              | `false` | 将详细的状态转换记录到控制台。                                 |
| **Validate On Start** | `true`  | 运行 `ValidateConfiguration()` 在 Start 时，并记录任何问题。 |

### 下一步

{% 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 %}

{% 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 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-narrative-design-triggers.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.
