> 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/unity-plugin-beta-overview/features/narrative-design/setting-up-narrative-design-triggers.md).

# 设置叙事设计触发器

全面解析 ConvaiNarrativeDesignTrigger 的四种激活模式——Collision、Proximity、TimeBased、Manual——以及队列系统、TriggerStatus 状态和每个触发器的 Unity Events。

## ConvaiNarrativeDesignTrigger 组件

`ConvaiNarrativeDesignTrigger` 向 Convai 后端发送一个命名信号，使故事图从一个部分推进到下一部分。它是一个世界空间组件：将它放在任何 GameObject 上——门、展品、UI 按钮的事件目标——并选择其激活方式。

{% hint style="info" %}
“叙事触发器”与 Unity 物理触发器并不相同，尽管其中一种激活模式使用 `OnTriggerEnter`。该触发器会向 Convai 后端发送一个命名信号。激活模式决定 *何时* 发送该信号。
{% endhint %}

## 添加组件

{% 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=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
**分配角色**

将你的 `ConvaiCharacter` 拖入 **Character** 字段中。如果留空， **自动查找角色** 会先搜索父级层级，然后 `ConvaiManager`的角色列表会自动搜索。如果场景中有多个角色，请显式指定目标。
{% endstep %}

{% step %}
**获取并选择一个触发器**

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

选择你希望此组件发送的触发器。 **触发器名称**, **触发器 ID**，以及 **目标章节** 字段会自动填充。

<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=""><figcaption></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=""><figcaption></figcaption></figure>

### 碰撞

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

**要求：**

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

**检测设置：**

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

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

### 接近

当玩家与该组件的 `Transform` 之间的距离落入 **接近半径**。检查会在每一帧的 `Update`.

在 Scene 视图中会绘制一个绿色球体（在选中 GameObject 时可见）来显示检测半径。你可以通过编辑 **接近半径** 字段直接调整其大小。

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

此模式不需要碰撞器。

### 基于时间

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

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

| 字段       | 默认         | 说明                    |
| -------- | ---------- | --------------------- |
| **时间延迟** | `0`        | 玩家在触发器触发前必须在区域内停留的秒数。 |
| **玩家标签** | `“Player”` | 用于识别玩家的标签。            |

### 手动

触发器不会自动执行任何操作。调用 `InvokeTrigger()` 或 `TryInvokeTrigger()` 即可从你自己的代码或 Unity 事件中触发它。

当激活条件完全由你的游戏逻辑控制时使用此模式——例如 UI 按钮、任务完成回调或一次得分交互。

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

// 仅在尚未触发时才触发（遵守 TriggerOnce）
narrativeTrigger.TryInvokeTrigger();
```

## 自动恢复设置

这些设置使触发器能够适应常见的运行时情况，即角色或玩家可能无法立即就绪。

<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=""><figcaption></figcaption></figure>

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

{% hint style="info" %}
“角色就绪”指的是 `ConvaiCharacter.IsInConversation` 是 `true` ——实时会话已打开。在会话打开之前发送的触发器会保留在队列中，并在连接建立后自动发送。你无需手动检查 `IsInConversation` ，再调用之前手动 `InvokeTrigger()`.
{% endhint %}

{% 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
    [*] --> 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 : 修复问题 + ResetTrigger()
    Ready --> Disabled : 组件或 GameObject 被禁用
    Disabled --> Ready : 组件或 GameObject 重新启用
```

有关每种状态的完整解决指南，请参阅故障排除与诊断。

## Inspector 参考

### 角色参考标题

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

### 触发器选择标题

| 字段         | 默认 | 说明                                                |
| ---------- | -- | ------------------------------------------------- |
| **触发器 ID** | 空  | 选择后为只读。来自仪表板的唯一标识符。                               |
| **触发器名称**  | 空  | 所选触发器的显示名称。                                       |
| **触发消息**   | 空  | 随触发器发送的可选消息负载。可通过编程方式设置，使用 `SetTriggerMessage()`. |

### 激活设置标题

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

### 自动恢复设置标题

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

### 诊断标题

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

## 结论

`ConvaiNarrativeDesignTrigger` 为你提供四种激活模式——Collision、Proximity、TimeBased 和 Manual——涵盖从简单的穿行区域到由 UI 驱动的代码流程的各种放置场景。内置队列系统、可配置超时和每个触发器的事件，使你无需编写自定义状态管理即可轻松处理边缘情况。继续学习 [模板键：动态叙事变量](/api-docs/zh/cha-jian-yu-ji-cheng/unity-plugin-beta-overview/features/narrative-design/template-keys-dynamic-narrative-variables.md) ，了解如何将玩家姓名或场景参数等运行时值注入角色目标中。


---

# 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/unity-plugin-beta-overview/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.
