> 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 Physics 触发器：激活模式控制 *当* 信号何时发送，而不是触发哪种 Unity 物理事件。

### 添加触发器组件

{% stepper %}
{% step %}

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

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

{% step %}

#### 添加该组件

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

<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 ID 从 **角色** 字段。如果留空， **自动查找角色** 会搜索父级层级，然后搜索 `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>带模式选择器的 Activation Settings 标题。</p></figcaption></figure>

#### 碰撞

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

**要求：**

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

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

**检测设置：**

| 字段               | 默认         | 说明                           |
| ---------------- | ---------- | ---------------------------- |
| **Player Tag**   | `"Player"` | 只有带此标签的 GameObject 才会被识别为玩家。 |
| **Player Layer** | 所有层        | 用于进一步筛选哪些对象被视为玩家的层遮罩。        |

#### Proximity

当玩家到该组件的距离 `Transform` 落在 **Proximity Radius**. 检查在 `更新`中每帧运行。场景视图中会绘制一个绿色球体，显示检测半径。

| 字段                   | 默认         | 说明                             |
| -------------------- | ---------- | ------------------------------ |
| **Proximity Radius** | `3`        | 以世界单位表示的检测半径。                  |
| **Player Tag**       | `"Player"` | 用于标识玩家的标签。                     |
| **自动查找玩家**           | `是`        | 如果未分配，则搜索场景中带标签的玩家 GameObject。 |

此模式不需要碰撞体。

#### 基于时间

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

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

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

#### 手动

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

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

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

### 触发请求模式

激活模式和触发请求模式是两个独立设置。激活模式（`碰撞`, `Proximity`, `基于时间`, `手动`）控制 *当* `ConvaiNarrativeDesignTrigger` 何时触发，如上所述。触发请求模式控制 *什么* 在触发后通过 RTVI 发送给 Convai。

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

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

| 触发请求模式           | 连接字段                                  | 发送方式                                                                                       |
| ---------------- | ------------------------------------- | ------------------------------------------------------------------------------------------ |
| `SavedTrigger`   | `trigger_name`                        | `ConvaiNarrativeDesignTrigger` （此组件），或 `IConvaiNarrativeDesign.InvokeTrigger(string)` 从代码中 |
| `InlineEvent`    | `trigger_message`                     | `IConvaiNarrativeDesign.InvokeEvent(string)` ——仅限代码，无 Inspector 对应项                        |
| `ScriptedSpeech` | `trigger_message` （包裹在 `<speak>` 标签中） | `IConvaiNarrativeDesign.InvokeSpeech(string)` ——仅限代码，无 Inspector 对应项                       |

`InlineEvent` 和 `ScriptedSpeech` 在此组件的 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>Auto-Recovery Settings 标题。</p></figcaption></figure>

| 字段          | 默认   | 说明                                                                                                              |
| ----------- | ---- | --------------------------------------------------------------------------------------------------------------- |
| **自动查找角色**  | `是`  | 搜索父级层级，然后 `ConvaiManager.Characters`。如果只有一个角色则自动分配；如果发现多个角色，则记录警告。                                              |
| **自动查找玩家**  | `是`  | 先按 Player Tag 搜索，再按常见名称列表搜索，然后通过 `Camera.main.parent`.                                                          |
| **等待就绪队列**  | `是`  | 如果角色尚未处于活动对话中（`IsInConversation` 是 `否`），则触发器会排队，并在连接建立时自动触发。你无需在调用 `IsInConversation` 之前手动检查 `InvokeTrigger()`. |
| **最大等待时间**  | `30` | 等待角色就绪的最长秒数。设为 `0` 表示不超时。                                                                                       |
| **场景加载时重置** | `是`  | 调用 `ResetTrigger()` 在加载任何场景时重置，以便触发器可以在重新加载的场景中再次触发。                                                            |

{% hint style="warning" %}
设置 **最大等待时间** 移动到 `0` 在会话可能永远不会连接的生产构建中，
{% endhint %}

### 控制触发频率

**仅触发一次** （默认 `是`）可防止触发器被触发超过一次。第一次成功调用后， `HasTriggered` 变为 `是`, `CurrentStatus` 变为 `AlreadyFired`，之后所有调用都返回 `否`.

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

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

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

若要让触发器在每次激活时都触发，请禁用 **仅触发一次** 检查器中进行配置。

### 事件参考

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

### 触发器状态

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

```mermaid
stateDiagram-v2
    [*] --> Ready
    Ready --> AlreadyFired : InvokeTrigger() 成功\n(TriggerOnce = true)
    Ready --> QueuedWaitingForCharacter : 调用 InvokeTrigger()\n角色未就绪\nQueueUntilReady = true
    Ready --> ConfigurationError : ValidateConfiguration() 失败
    QueuedWaitingForCharacter --> AlreadyFired : 角色变为就绪
    QueuedWaitingForCharacter --> ConfigurationError : 超过 MaxWaitTime
    AlreadyFired --> Ready : ResetTrigger()
    ConfigurationError --> Ready : 修复问题 + ValidateConfiguration()
    Ready --> Disabled : 组件或 GameObject 被禁用
    Disabled --> Ready : 组件或 GameObject 重新启用
```

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

### 检查器参考

#### 角色引用标题

| 字段         | 默认  | 说明                                                |
| ---------- | --- | ------------------------------------------------- |
| **角色**     | 无   | 目标 `ConvaiCharacter`。如果为空则自动查找，并且 **自动查找角色** 已启用。 |
| **自动查找角色** | `是` | 当 Character 字段为空时，搜索层级和 ConvaiManager。            |

#### 触发器选择标题

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

#### 激活设置标题

| 字段                   | 默认         | 说明                                         |
| -------------------- | ---------- | ------------------------------------------ |
| **激活模式**             | `碰撞`       | 触发器如何激活： `碰撞`, `Proximity`, `手动`，或 `基于时间`. |
| **Proximity Radius** | `3`        | Proximity 模式的检测半径。                         |
| **时间延迟**             | `0`        | TimeBased 模式的倒计时秒数。                        |
| **仅触发一次**            | `是`        | 如果启用，则在 `ResetTrigger()` 被调用。              |
| **Player Layer**     | 全部         | 用于玩家检测的层遮罩。                                |
| **Player Tag**       | `"Player"` | 用于识别玩家 GameObject 的标签。                     |

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

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

#### 诊断标题

| 字段        | 默认  | 说明                                            |
| --------- | --- | --------------------------------------------- |
| **启用诊断**  | `否` | 将详细状态转换记录到 Console。                           |
| **启动时验证** | `是` | 运行 `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 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/setting-up-narrative-design-triggers.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.
