> 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/core-concepts/event-system.md).

# 事件系统

Convai SDK 通过一组中继组件来传达会话期间发生的事情——连接、角色语音、转录文本、情绪等。将这些 MonoBehaviour 之一添加到场景中的 GameObject 上，在 Inspector 中连接 UnityEvents，或者在代码中订阅，场景逻辑就会对 SDK 广播的内容作出响应。

***

### 两种接线方式

{% tabs %}
{% tab title="Inspector（UnityEvents）" %}

1. 通过以下路径将中继组件添加到场景中的任意 GameObject： **Add Component → Convai → Events**.
2. 在 Inspector 中分配所需引用（`ConvaiManager` 或 `ConvaiCharacter`)，或者启用 **Auto Resolve** ，让组件自动查找它。
3. 在 Inspector 中将处理程序连接到 UnityEvent 字段——无需编写代码。

最适合：连接指示器、动画触发器、UI 显示切换——任何由单个事件驱动且不需要条件逻辑的内容。
{% endtab %}

{% tab title="C# 脚本" %}
从代码中订阅中继组件事件：

```csharp
public class MyHandler : MonoBehaviour
{
    [SerializeField] private ConvaiCharacterEventRelay _relay;

    private void OnEnable()
    {
        _relay.OnEmotionChanged.AddListener(HandleEmotion);
        _relay.OnSpeechStarted.AddListener(HandleSpeechStarted);
    }

    private void OnDisable()
    {
        _relay.OnEmotionChanged.RemoveListener(HandleEmotion);
        _relay.OnSpeechStarted.RemoveListener(HandleSpeechStarted);
    }

    private void HandleEmotion(CharacterEmotionRelayData data) { /* … */ }
    private void HandleSpeechStarted() { /* … */ }
}
```

最适合：条件逻辑、多事件协调、跨多个系统的数据路由。
{% endtab %}
{% endtabs %}

***

### 中继组件速查

| 组件                           | Inspector 菜单路径                              | 使用场景                        |
| ---------------------------- | ------------------------------------------- | --------------------------- |
| `ConvaiSessionEventRelay`    | Convai/Events/Convai Session Event Relay    | 跟踪会话连接状态、处理错误、驱动连接 UI       |
| `ConvaiCharacterEventRelay`  | Convai/Events/Convai Character Event Relay  | 响应特定角色的语音、转录、轮次和情绪          |
| `ConvaiTranscriptEventRelay` | Convai/Events/Convai Transcript Event Relay | 整个场景范围内的转录流，可按角色或最终状态进行可选过滤 |

***

### `ConvaiSessionEventRelay`

跟踪整个场景的会话生命周期。每个场景添加一个——它会监控由 `ConvaiManager`.

{% hint style="info" %}
如果 `ConvaiManager` 初始化后，若中继的 `OnEnable` （例如由于脚本执行顺序），中继会在 `LateUpdate()` 处于启用状态时自动重试订阅。无需手动重试逻辑。
{% endhint %}

**检查器字段：**

| 字段                   | 描述                                                                     |
| -------------------- | ---------------------------------------------------------------------- |
| `管理器`                | 对 `ConvaiManager` 持有一条成员关系。                                            |
| `AutoResolveManager` | 的引用。启用后，组件会在运行时查找 `ConvaiManager.ActiveManager` 。如果你有多个管理器或需要显式绑定，请禁用。 |

**事件：**

| 事件                                | 有效载荷                              | 触发时机                                                                                                                         |
| --------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `OnConnected`                     | —                                 | 建立初始连接（`Connecting` → `Connected`）。不会在重连时触发——请参见 `OnReconnected`.                                                            |
| `OnDisconnected`                  | —                                 | 会话进入 `Disconnected` 状态。                                                                                                      |
| `OnReconnecting`                  | —                                 | 开始尝试重新连接（会话曾处于 `Connected`，连接已断开）。                                                                                           |
| `OnReconnected`                   | —                                 | 重新连接尝试成功。会话再次处于 `Connected` 状态。                                                                                              |
| `OnUsageLimitReached`             | —                                 | 账户的 API 使用配额已超出。                                                                                                             |
| `OnUserIdleWarning`               | `UserIdleWarningRelayData`        | 已达到用户空闲警告阈值。请参见 [会话生命周期](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/session-lifecycle.md) 中触发此事件的超时策略。 |
| `OnUserIdleTimeout`               | `UserIdleTimeoutRelayData`        | 在发出警告后，若没有 `ExtendIdleTimeout`/`ResetIdleTimer` 调用，本地推导出的空闲截止时间到期。                                                           |
| `OnRuntimeBackgroundStateChanged` | `RuntimeBackgroundStateRelayData` | 应用进入或离开后台，或者其实际后台策略发生变化。                                                                                                     |
| `OnSessionStateChanged`           | `SessionStateChangedRelayData`    | 任何会话状态转换。每次状态变化都会触发。                                                                                                         |
| `OnSessionError`                  | `SessionErrorRelayData`           | 从会话接收到错误事件。                                                                                                                  |

#### `SessionStateChangedRelayData`

| 属性          | 类型             | 描述                                                         |
| ----------- | -------------- | ---------------------------------------------------------- |
| `旧状态`       | `SessionState` | 转换前的状态。                                                    |
| `新状态`       | `SessionState` | 转换后的状态。                                                    |
| `SessionId` | `string`       | 当前会话标识符。如果没有活动会话，则为空。                                      |
| `错误代码`      | `string`       | 如果转换是由错误引起，则为错误代码；否则为空。                                    |
| `是否为错误`     | `布尔值`          | 计算结果： `NewState == Error`.                                 |
| `正在重新连接`    | `布尔值`          | 计算结果： `OldState == Connected && NewState == Reconnecting`. |
| `连接已建立`     | `布尔值`          | 计算结果： `OldState == Connecting && NewState == Connected`.   |
| `重连成功`      | `布尔值`          | 计算结果： `OldState == Reconnecting && NewState == Connected`. |
| `已断开连接`     | `布尔值`          | 计算结果： `NewState == Disconnected`.                          |

#### `SessionErrorRelayData`

| 属性               | 类型                  | 描述                           |
| ---------------- | ------------------- | ---------------------------- |
| `错误代码`           | `string`            | 机器可读的错误代码。                   |
| `消息`             | `string`            | 人类可读的错误描述。                   |
| `SessionId`      | `string`            | 发生错误时的会话标识符。                 |
| `是否可恢复`          | `布尔值`               | SDK 是否会尝试自动恢复。               |
| `阶段`             | `SessionErrorStage` | 错误在连接生命周期中的哪个阶段发生。           |
| `HttpStatusCode` | `int`               | 如果错误源自 API 调用，则为 HTTP 状态码。   |
| `是否包含 Http 状态码`  | `布尔值`               | 是否 `HttpStatusCode` 包含有意义的值。 |

`SessionErrorStage` 值： `未知`, `配置`, `ConnectApi`, `Transport`, `SessionRecovery`, `Runtime`.

#### `UserIdleWarningRelayData`

| 属性     | 类型       | 描述                     |
| ------ | -------- | ---------------------- |
| `剩余秒数` | `int`    | 在本地推导出的空闲截止时间到期前剩余的秒数。 |
| `消息`   | `string` | 人类可读的空闲警告消息。           |

#### `UserIdleTimeoutRelayData`

| 属性                     | 类型       | 描述                          |
| ---------------------- | -------- | --------------------------- |
| `WarningReceivedAtUtc` | `string` | 接收到空闲警告时的 ISO 8601 时间戳。     |
| `DeadlineUtc`          | `string` | 本地推导出的空闲截止时间的 ISO 8601 时间戳。 |

#### `RuntimeBackgroundStateRelayData`

| 属性                     | 类型                        | 描述                                                            |
| ---------------------- | ------------------------- | ------------------------------------------------------------- |
| `是否处于后台`               | `布尔值`                     | 应用当前是否处于后台。                                                   |
| `请求的策略`                | `RuntimeBackgroundPolicy` | 你的项目配置的后台策略。                                                  |
| `实际生效的策略`              | `RuntimeBackgroundPolicy` | 当前实际生效的后台策略。在某些强制回退的平台上，可能与 `请求的策略` 不同。                       |
| `原因`                   | `RuntimePauseReason`      | 状态变化的原因——例如 `ApplicationBackground` 或 `ApplicationFocusLost`. |
| `UsedPlatformFallback` | `布尔值`                     | 计算结果： `true` 当 `RequestedPolicy != EffectivePolicy`.          |

`RuntimeBackgroundPolicy` 以及完整的暂停/恢复/重连 API 均在 [会话生命周期](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/session-lifecycle.md)中介绍；本页只记录事件有效载荷。

**代码示例——显示连接状态指示器：**

```csharp
public class ConnectionIndicator : MonoBehaviour
{
    [SerializeField] private ConvaiSessionEventRelay _relay;
    [SerializeField] private GameObject _connectingOverlay;

    private void OnEnable()
    {
        _relay.OnConnected.AddListener(OnConnected);
        _relay.OnDisconnected.AddListener(OnDisconnected);
        _relay.OnReconnecting.AddListener(OnReconnecting);
    }

    private void OnDisable()
    {
        _relay.OnConnected.RemoveListener(OnConnected);
        _relay.OnDisconnected.RemoveListener(OnDisconnected);
        _relay.OnReconnecting.RemoveListener(OnReconnecting);
    }

    private void OnConnected()    => _connectingOverlay.SetActive(false);
    private void OnDisconnected() => _connectingOverlay.SetActive(true);
    private void OnReconnecting() => _connectingOverlay.SetActive(true);
}
```

***

### `ConvaiCharacterEventRelay`

跟踪单个 `ConvaiCharacter`的事件。每个需要驱动场景响应的角色添加一个。

**检查器字段：**

| 字段                     | 描述                                                 |
| ---------------------- | -------------------------------------------------- |
| `角色`                   | 对 `ConvaiCharacter` 此中继会监控。                        |
| `AutoResolveCharacter` | 启用后，组件会搜索 `ConvaiCharacter` 中继所在的同一个 GameObject 上。 |

**事件：**

| 事件                     | 有效载荷                              | 触发时机                      |
| ---------------------- | --------------------------------- | ------------------------- |
| `OnTranscriptReceived` | `CharacterTranscriptRelayData`    | 每个转录片段到达时——包括中间（部分）和最终片段。 |
| `OnSpeechStarted`      | —                                 | 角色开始说话（音频开始播放）。           |
| `OnSpeechStopped`      | —                                 | 角色停止说话（音频结束）。             |
| `OnTurnCompleted`      | `CharacterTurnCompletedRelayData` | 角色的一轮完整回复已完成。             |
| `OnCharacterReady`     | —                                 | 角色已完全初始化并连接到会话。           |
| `OnEmotionChanged`     | `CharacterEmotionRelayData`       | 从 Convai 收到新的情绪信号。        |

#### 多角色房间中的事件

当多角色会话处于活动状态时， `ConvaiCharacterEventRelay` 以及 `ConvaiEvents` 上的按角色事件会通过房间成员关系而不是仅通过 `CharacterId` 来解析传入消息。一个名册可以包含两个具有相同 `CharacterId`的成员关系，只有成员关系才能将它们区分开来——仅按 `CharacterId` 过滤的代码无法区分这两者。请参见 [响应名册和目标变化](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/handle-roster-events.md) 中基于成员关系范围的事件。 `MultiCharacterRoomSession`.

#### `CharacterTranscriptRelayData`

| 属性              | 类型       | 描述                                  |
| --------------- | -------- | ----------------------------------- |
| `CharacterId`   | `string` | 角色的 ID。                             |
| `CharacterName` | `string` | 角色的显示名称。                            |
| `文本`            | `string` | 转录文本。如果 `IsFinal` 为 false，则可能是部分文本。 |
| `IsFinal`       | `布尔值`    | 指示底层转录轮次是已提交、中断还是已更正。               |
| `TurnId`        | `string` | 标识此转录片段所属的轮次。                       |
| `MessageId`     | `string` | 此转录消息的唯一标识符。                        |
| `ResponseId`    | `string` | 标识该轮次所属的角色回复。                       |

#### `CharacterTurnCompletedRelayData`

| 属性               | 类型       | 描述               |
| ---------------- | -------- | ---------------- |
| `CharacterId`    | `string` | 角色的 ID。          |
| `CharacterName`  | `string` | 角色的显示名称。         |
| `WasInterrupted` | `布尔值`    | 该轮次是否因用户打断角色而结束。 |

#### `CharacterEmotionRelayData`

| 属性              | 类型       | 描述                                                  |
| --------------- | -------- | --------------------------------------------------- |
| `CharacterId`   | `string` | 角色的 ID。                                             |
| `CharacterName` | `string` | 角色的显示名称。                                            |
| `Emotion`       | `string` | 情绪名称（例如， `"joy"`, `"fear"`, `"sadness"`）。请参见情绪功能参考。 |
| `Intensity`     | `int`    | 情绪强度，采用 `1`–`3` 级量表，其中 `1` 表示轻微， `3` 表示强烈。          |

**代码示例——在情绪变化时触发动画：**

```csharp
public class CharacterEmotionAnimator : MonoBehaviour
{
    [SerializeField] private ConvaiCharacterEventRelay _relay;
    [SerializeField] private Animator _animator;

    private static readonly int EmotionHash = Animator.StringToHash("Emotion");

    private void OnEnable() => _relay.OnEmotionChanged.AddListener(HandleEmotion);
    private void OnDisable() => _relay.OnEmotionChanged.RemoveListener(HandleEmotion);

    private void HandleEmotion(CharacterEmotionRelayData data)
    {
        _animator.SetTrigger(data.Emotion);
        _animator.SetFloat("EmotionIntensity", data.Intensity / 3f);
    }
}
```

***

### `ConvaiTranscriptEventRelay`

提供整个场景范围内的转录流。与 `ConvaiCharacterEventRelay`不同，这个中继通过单个组件监控所有角色和玩家。可用于驱动字幕 UI、会话日志或评估系统。

**检查器字段：**

| 字段                     | 类型              | 默认值     | 描述                                                                                 |
| ---------------------- | --------------- | ------- | ---------------------------------------------------------------------------------- |
| `管理器`                  | `ConvaiManager` | —       | 当前交互目标的 `ConvaiManager` 进行监控。                                                      |
| `AutoResolveManager`   | `布尔值`           | —       | 查找 `ActiveManager` 自动。                                                             |
| `FinalOnly`            | `布尔值`           | `false` | 启用后，仅最终转录（已提交、中断或已更正）会触发事件。中间的部分转录会被抑制。                                            |
| `IgnoreInterimUpdates` | `布尔值`           | `true`  | 丢弃仍处于 `Listening` 或 `Streaming` 状态的轮次。稳定且已提交的轮次仍会通过。如果你的 UI 需要在角色说话时显示部分文本，请禁用此字段。 |
| `CharacterIdFilter`    | `string`        | `""`    | 如果设置，只会触发此 ID 角色的转录事件。留空则适用于所有角色。                                                  |

**事件：**

| 事件                                   | 有效载荷                           | 触发时机                                                  |
| ------------------------------------ | ------------------------------ | ----------------------------------------------------- |
| `OnTranscriptReceived`               | `TranscriptUpdateRelayData`    | 任何角色或玩家的转录更新，使用单一统一结构（受过滤条件和 `IgnoreInterimUpdates`). |
| `OnCharacterTranscriptReceived`      | `CharacterTranscriptRelayData` | 任何角色转录（受过滤条件和 `IgnoreInterimUpdates`).                |
| `OnPlayerTranscriptReceived`         | `PlayerTranscriptRelayData`    | 任何玩家转录。                                               |
| `OnFinalCharacterTranscriptReceived` | `CharacterTranscriptRelayData` | 仅最终角色转录，不受 `FinalOnly` 设置影响。                          |
| `OnFinalPlayerTranscriptReceived`    | `PlayerTranscriptRelayData`    | 仅最终玩家转录。                                              |

#### `TranscriptUpdateRelayData`

当场景需要一个事件和一种数据结构同时处理角色与玩家的转录更新，而不是分别订阅角色和玩家事件时，请使用此有效载荷。

| 属性                    | 类型                            | 描述                                        |
| --------------------- | ----------------------------- | ----------------------------------------- |
| `MessageId`           | `string`                      | 此转录消息的唯一标识符。                              |
| `TurnId`              | `string`                      | 标识此更新所属的轮次。                               |
| `ResponseId`          | `string`                      | 标识该轮次所属的角色回复。                             |
| `SpeakerType`         | `SpeakerType`                 | `角色` 或 `Player`.                          |
| `PlayerOrCharacterId` | `string`                      | 正在说话的角色或玩家 ID。                            |
| `DisplayName`         | `string`                      | 说话者的显示名称。                                 |
| `ParticipantId`       | `string`                      | 房间参与者标识符。                                 |
| `文本`                  | `string`                      | 转录文本。如果 `IsFinal` 为 false，则可能是部分文本。       |
| `生命周期`                | `TranscriptLifecycle`         | `Streaming`, `稳定`，或者 `已完成` ——本次更新文本的确定程度。 |
| `IsFinal`             | `布尔值`                         | 计算结果： `Lifecycle != Streaming`.           |
| `SourceKind`          | `TranscriptSegmentSourceKind` | 文本来源——例如 `PlayerAsr` 或 `BotOutput`.       |

#### `PlayerTranscriptRelayData`

| 属性              | 类型       | 描述                                  |
| --------------- | -------- | ----------------------------------- |
| `PlayerId`      | `string` | 本地玩家的标识符。                           |
| `PlayerName`    | `string` | 玩家的显示名称。                            |
| `SpeakerId`     | `string` | 说话者标识符（在多参与者房间中可能与 `PlayerId` 不同）。  |
| `SpeakerName`   | `string` | 说话者的显示名称。                           |
| `ParticipantId` | `string` | 房间参与者标识符。                           |
| `TurnId`        | `string` | 标识此转录片段所属的轮次。                       |
| `MessageId`     | `string` | 此转录消息的唯一标识符。                        |
| `文本`            | `string` | 转录文本。如果 `IsFinal` 为 false，则可能是部分文本。 |
| `IsFinal`       | `布尔值`    | 指示底层转录轮次是已提交、中断还是已更正。               |

**代码示例——用于训练日志的多角色转录流：**

```csharp
public class TrainingTranscriptLog : MonoBehaviour
{
    [SerializeField] private ConvaiTranscriptEventRelay _relay;
    [SerializeField] private TMP_Text _logText;

    private readonly System.Text.StringBuilder _log = new();

    private void OnEnable()
    {
        _relay.OnFinalCharacterTranscriptReceived.AddListener(OnCharacterLine);
        _relay.OnFinalPlayerTranscriptReceived.AddListener(OnPlayerLine);
    }

    private void OnDisable()
    {
        _relay.OnFinalCharacterTranscriptReceived.RemoveListener(OnCharacterLine);
        _relay.OnFinalPlayerTranscriptReceived.RemoveListener(OnPlayerLine);
    }

    private void OnCharacterLine(CharacterTranscriptRelayData data)
    {
        _log.AppendLine($"[{data.CharacterName}]: {data.Text}");
        _logText.text = _log.ToString();
    }

    private void OnPlayerLine(PlayerTranscriptRelayData data)
    {
        _log.AppendLine($"[Learner]: {data.Text}");
        _logText.text = _log.ToString();
    }
}
```

***

### 订阅生命周期

Relay MonoBehaviour 组件会自动管理自己的订阅。它们会在 `OnEnable` 运行时订阅，并在 `OnDisable` 运行之前注册。

通过 C# 订阅时，请遵循相同模式：

```csharp
private void OnEnable()  => _relay.OnConnected.AddListener(MyHandler);
private void OnDisable() => _relay.OnConnected.RemoveListener(MyHandler);
```

{% hint style="warning" %}
不要在 `Start()` 中订阅，而不在 `OnDestroy()`中进行匹配的取消订阅。中继组件可以被禁用后再重新启用；如果在 `Start()` 中没有清理就进行订阅，那么中继被禁用后会导致重复处理程序或空引用错误。
{% endhint %}

***

### `ConvaiNotificationEventBridge`

`ConvaiNotificationEventBridge` 不是一个中继组件。它是一个内部服务，用于将会话错误域事件桥接到通知 UI 系统，并带有冷却去重机制，以防同一错误通知反复出现。

| 属性                | 类型      | 默认值  | 描述                  |
| ----------------- | ------- | ---- | ------------------- |
| `CooldownSeconds` | `float` | `10` | 显示同一种通知类型之间的最小秒数间隔。 |

大多数项目不会直接与此类交互。它由 SDK 启动流程实例化并管理。如果你正在使用 `IConvaiNotificationService`构建自定义通知系统，你可以使用 `ConvaiNotificationEventBridge` 将会话错误事件集成到你的系统中。与上面的中继组件不同， `ConvaiNotificationEventBridge` 不是通过 **Add Component** 添加到场景中的——它是在 SDK 启动期间以程序方式实例化的。

***

### 使用示例

#### 示例 1：培训模拟——连接覆盖层

在会话尚未建立时显示“Connecting…”覆盖层。

```csharp
[SerializeField] private ConvaiSessionEventRelay _sessionRelay;
[SerializeField] private CanvasGroup _loadingOverlay;

private void OnEnable()
{
    _sessionRelay.OnConnected.AddListener(OnConnected);
    _sessionRelay.OnDisconnected.AddListener(OnDisconnected);
    _sessionRelay.OnReconnecting.AddListener(OnReconnecting);
}

private void OnDisable()
{
    _sessionRelay.OnConnected.RemoveListener(OnConnected);
    _sessionRelay.OnDisconnected.RemoveListener(OnDisconnected);
    _sessionRelay.OnReconnecting.RemoveListener(OnReconnecting);
}

private void OnConnected()    => _loadingOverlay.alpha = 0f;
private void OnDisconnected() => _loadingOverlay.alpha = 1f;
private void OnReconnecting() => _loadingOverlay.alpha = 0.5f;
```

**预期结果：** 当会话尚未连接时，覆盖层淡入；连接建立后，覆盖层淡出。

***

#### 示例 2：医疗培训师——由情绪触发的角色反应

患者角色的面部表情和姿态会根据 Convai 检测到的情绪而变化。

```csharp
[SerializeField] private ConvaiCharacterEventRelay _patientRelay;
[SerializeField] private PatientExpressionController _expressionController;

private void OnEnable() => _patientRelay.OnEmotionChanged.AddListener(ApplyEmotion);
private void OnDisable() => _patientRelay.OnEmotionChanged.RemoveListener(ApplyEmotion);

private void ApplyEmotion(CharacterEmotionRelayData data)
{
    _expressionController.SetExpression(data.Emotion, data.Intensity / 3f);
}
```

**预期结果：** 当来自 Convai 的情绪信号到来时，患者角色的视觉表情会实时更新。

***

#### 示例 3：过滤到单个角色的共享转录流

一个企业入职模拟中有多个 NPC 角色，但只有主讲导师的台词会显示在字幕面板中。

在 `ConvaiTranscriptEventRelay` 检查器中的组件：

* 设置为 `CharacterIdFilter` 到讲师角色的 ID（例如， `"abc123"`).
* 启用 `FinalOnly` 以仅显示已提交的转录行。
* 连接 `OnFinalCharacterTranscriptReceived` 到你的字幕 UI。

**预期结果：** 只有讲师已完成的句子会显示在字幕面板中。场景中的其他角色不会影响 UI。

***

### 故障排查

| 症状                                       | 可能原因                                           | 修复方法                                                                                                                    |
| ---------------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 场景开始后 Relay 不触发任何事件                      | `ConvaiManager` 在该 Relay 的 `OnEnable` 运行之前未初始化 | 无需操作——Relay 将在 `LateUpdate()` 在启用状态下。请验证 `ConvaiManager` 已存在并在场景中处于活动状态。                                                |
| `ConvaiCharacterEventRelay` 不触发任何事件      | `ConvaiCharacter` 未在分配的 GameObject 上找到         | 验证 `ConvaiCharacter` 位于 **同一个** 与 Relay 相同的 GameObject 上，或者显式分配该引用。 `AutoResolveCharacter` 只会搜索同一个 GameObject——不会搜索父对象。 |
| 中间转录更新未到达                                | `IgnoreInterimUpdates` 是 `true` 默认情况下          | 设置为 `IgnoreInterimUpdates = false` 时自行注册 `ConvaiTranscriptEventRelay` 以接收部分转录更新。                                        |
| 事件处理器对单个事件触发多次                           | 处理器在 `Start()` 中订阅，且未清理；Relay 被禁用后又重新启用        | 将订阅移至 `OnEnable()` 并在 `OnDisable()`.                                                                                    |
| `OnCharacterTranscriptReceived` 未对预期角色触发 | `CharacterIdFilter` 被设置为不同的角色 ID               | 清除 `CharacterIdFilter` 或者将其设置为正确的角色 ID。                                                                                 |

***

### 下一步

你现在已经拥有所有 Relay 组件、事件载荷和订阅模式的完整参考。请继续查看 Features 部分，了解各项 SDK 功能。

{% content-ref url="/pages/8c561f7c198c46628ed5818040fdaa9af3397caf" %}
[功能](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features.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/core-concepts/event-system.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.
