> 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/multi-character-sessions/connection-api-reference.md).

# 连接 API 参考

多角色连接操作、其加入与连接选项类型，以及每个操作可能抛出的所有异常的参考。

本页列出了……的多角色成员 `IConvaiRoomConnectionService`， `MultiCharacterJoinOptions` 类型、 `RoomSessionConnectOptions`上的多角色字段，以及每个操作产生的异常和超时。所有类型都位于 `Convai.Runtime.Room` 命名空间。

***

### `IConvaiRoomConnectionService` — 多角色成员

定义于 `SDK/Runtime/Room/IConvaiRoomConnectionService.cs:68-147`。通过以下方式访问该服务 `ConvaiManager.ActiveManager.TryGetRoomConnectionService(out IConvaiRoomConnectionService roomService)`.

| 成员                             | 签名                                                                                                                                                  | 返回值                                             |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `CurrentMultiCharacterSession` | `MultiCharacterRoomSession CurrentMultiCharacterSession { get; }`                                                                                   | 当前房间的规范名册，或 `null` 单角色房间的名册。                    |
| `JoinMultiCharacterRoomAsync`  | `JoinMultiCharacterRoomAsync(MultiCharacterJoinOptions options, CancellationToken cancellationToken = default)`                                     | `IConvaiOperation<RoomSession>`                 |
| `SetInteractionTargetAsync`    | `SetInteractionTargetAsync(IConvaiCharacterAgent character, CancellationToken cancellationToken = default)`                                         | `IConvaiOperation<InteractionTargetResult>`     |
| `SetInteractionTargetAsync`    | `SetInteractionTargetAsync(string membershipId, CancellationToken cancellationToken = default)`                                                     | `IConvaiOperation<InteractionTargetResult>`     |
| `ClearInteractionTargetAsync`  | `ClearInteractionTargetAsync(CancellationToken cancellationToken = default)`                                                                        | `IConvaiOperation<InteractionTargetResult>`     |
| `AddCharacterAsync`            | `AddCharacterAsync(IConvaiCharacterAgent character, string characterSessionId = null, CancellationToken cancellationToken = default)`               | `IConvaiOperation<CharacterRosterUpdateResult>` |
| `RemoveCharacterAsync`         | `RemoveCharacterAsync(string membershipId, string replacementTargetMembershipId = null, CancellationToken cancellationToken = default)`             | `IConvaiOperation<CharacterRosterUpdateResult>` |
| `RemoveCharacterAsync`         | `RemoveCharacterAsync(IConvaiCharacterAgent character, string replacementTargetMembershipId = null, CancellationToken cancellationToken = default)` | `IConvaiOperation<CharacterRosterUpdateResult>` |

参见 [操作与流类型](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/operation-and-stream-types.md) 关于如何使用 `IConvaiOperation<T>`。结果和异常类型在以下位置有文档说明 [房间会话引用](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/room-session-reference.md).

***

### 并发门控

`ConvaiRoomManager` 通过各自的 `SemaphoreSlim(1, 1)`串行化每个命令族，定义于 `SDK/Runtime/Adapters/Networking/ConvaiRoomManager.Connection.cs:29-30`。任一时刻最多只有一次名册修改和一次交互目标更改在进行中。

| 门控                               | 保护                                                               |
| -------------------------------- | ---------------------------------------------------------------- |
| `_rosterMutationGate`            | `AddCharacterAsync`，两个 `RemoveCharacterAsync` 重载                 |
| `_interactionTargetMutationGate` | 两个 `SetInteractionTargetAsync` 重载， `ClearInteractionTargetAsync` |

同一命令族的第二次调用会等待第一次完成，而不是并发运行。

***

### 异常和超时

每个操作都会使其 `IConvaiOperation<T>` 任务进入故障状态，而不是同步抛出异常。请在 await 的任务上处理该异常。

#### 适用于所有操作的前置条件

| 条件                       | 异常                          | 消息                     |
| ------------------------ | --------------------------- | ---------------------- |
| 没有处于活动状态的多角色房间           | `InvalidOperationException` | `多角色房间会话未处于活动状态。`      |
| 当某个命令在其门控上等待时，多角色房间发生了变化 | `InvalidOperationException` | `当此更新在等待时，多角色房间发生了变化。` |
| 房间数据通道未就绪                | `InvalidOperationException` | `房间数据通道未就绪。`           |

#### `JoinMultiCharacterRoomAsync`

| 条件                          | 异常                         | 消息           |
| --------------------------- | -------------------------- | ------------ |
| `options` 是 `null`          | `ArgumentNullException`    | —（`options`) |
| Convai 拒绝加入，或者底层连接尝试以其他方式失败 | `ConvaiOperationException` | 后端会话错误代码和消息。 |

`JoinMultiCharacterRoomAsync` 转换为 `options` 一个 `RoomSessionConnectOptions` 与 `JoinExistingMultiCharacterRoom` 设置为 `是`，然后调用与 `ConnectAsync` (`ConvaiRoomManager.Connection.cs:58-66`相同的连接路径）。它不会发送名册，因此 [连接时的名册验证](#connect-time-roster-validation) 中的名册验证异常不适用于它——但它会继承 `ConnectAsync`的其他失败模式，包括一个 `ConvaiOperationException` 用于被拒绝或无法到达的连接。请参见 [加入现有房间](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/join-an-existing-session.md#troubleshooting) 以了解仅针对加入的原因及其修复方法。

#### `SetInteractionTargetAsync`

`SetInteractionTargetAsync` 有两个重载：一个接受一个 `IConvaiCharacterAgent`，另一个接受一个 `membershipId` string。两者共享相同的超时和确认失败行为；只有“不是成员”的检查会因参数而异。

| 条件                               | 异常                          | 消息                                    |
| -------------------------------- | --------------------------- | ------------------------------------- |
| 角色重载的 `character` 不是当前房间的成员      | `ArgumentException`         | `该角色不是当前房间的成员。` (`character`)         |
| 成员 ID 重载的 `membershipId` 不属于当前房间 | `ArgumentException`         | `该成员不属于当前房间。` (`membershipId`)        |
| 当命令在门控上等待时，目标成员已被移除              | `InvalidOperationException` | `当此更新在等待时，交互目标已被移除。`                  |
| 10 秒内未收到确认                       | `TimeoutException`          | `等待交互目标确认时超时。`                        |
| Convai 的确认报告了非成功状态               | `InvalidOperationException` | 后端消息，或 `交互目标更新失败。` 当 Convai 未报告任何消息时。 |

#### `ClearInteractionTargetAsync`

`ClearInteractionTargetAsync` 会发送一个空目标，因此“等待期间被移除”的检查不适用。它与上面的两个 `SetInteractionTargetAsync` 重载共享相同的超时和确认失败行为。

{% hint style="info" %}
清除交互目标不会中断角色已经在播放的音频。它只会阻止新的玩家输入路由到该角色。
{% endhint %}

#### `AddCharacterAsync`

| 条件                         | 异常                               | 消息                                                                                                                                                                                                |
| -------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `character` 是 `null`       | `ArgumentNullException`          | —（`character`)                                                                                                                                                                                    |
| `character.CharacterId` 为空 | `ArgumentException`              | `该角色必须具有 character ID。` (`character`)                                                                                                                                                             |
| 本地角色实例已是房间成员               | `ArgumentException`              | `此本地角色实例已是当前房间的成员。添加克隆时请使用另一个实例。` (`character`)                                                                                                                                                   |
| 当此命令在门控上等待时，添加了相同的本地角色     | `InvalidOperationException`      | `当此名册更新在等待时，已添加了本地角色。`                                                                                                                                                                            |
| 15 秒内未收到确认                 | `TimeoutException`               | `等待角色名册更新确认时超时。`                                                                                                                                                                                  |
| Convai 的确认报告了非成功状态         | `CharacterRosterUpdateException` | 后端消息，或 `角色花名册更新失败。` 当 Convai 未报告任何消息时。参见 [房间会话引用](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/room-session-reference.md#characterrosterupdateexception). |

#### `RemoveCharacterAsync`

`RemoveCharacterAsync` 有两个重载：一个接受一个 `membershipId` string，另一个接受一个 `IConvaiCharacterAgent`。两者共享相同的替换目标和门控竞争检查；只有“不是成员”的检查会因参数而异。

| 条件                                          | 异常                               | 消息                                                    |
| ------------------------------------------- | -------------------------------- | ----------------------------------------------------- |
| 角色重载的 `character` 是 `null`                  | `ArgumentNullException`          | —（`character`)                                        |
| 成员 ID 重载的 `membershipId` 不属于当前房间            | `ArgumentException`              | `该成员不属于当前房间。` (`membershipId`)                        |
| 角色重载的 `character` 不是当前房间的成员                 | `ArgumentException`              | `该角色不是当前房间的成员。` (`character`)                         |
| `replacementTargetMembershipId` 不属于当前房间     | `ArgumentException`              | `替换目标不属于当前房间。` (`replacementTargetMembershipId`)      |
| `replacementTargetMembershipId` 等于正在移除的成员资格 | `ArgumentException`              | `替换目标不能是正在移除的成员资格。` (`replacementTargetMembershipId`) |
| 当命令在门控上等待时，正在移除的成员资格已被移除                    | `InvalidOperationException`      | `当此名册更新在等待时，角色成员资格已被移除。`                              |
| 当命令在门控上等待时，替换目标已被移除                         | `InvalidOperationException`      | `当此名册更新在等待时，替换目标已被移除。`                                |
| 15 秒内未收到确认                                  | `TimeoutException`               | `等待角色名册更新确认时超时。`                                      |
| Convai 的确认报告了非成功状态                          | `CharacterRosterUpdateException` | 后端消息，或 `角色花名册更新失败。` 当 Convai 未报告任何消息时。                |

{% hint style="warning" %}
替换目标必须已经是房间成员，并且不能是正在移除的成员资格。名册绝不可能变为空：在没有有效替换的情况下移除活动成员资格，会清除目标，而不是删除最后一个成员资格。
{% endhint %}

***

### 连接时的名册验证

注册了两个或更多角色的场景会在 `ConnectAsync`期间构建其名册，在上述任何操作运行之前。SDK 在 `RoomConnectionRuntimeAdapter.ApplyMultiCharacterTopology` 中验证该名册，并对下面每个条件 `ConvaiOperationException` 按此顺序检查时抛出一个 `ConnectionFailure` ，其中携带 `SessionErrorCodes.ConnectionFailed`。调用方看到一个 `ConvaiOperationException` 带有 **原始消息** 如下，但其 `代码` 是 `ConnectionFailed` —— 原始代码（`ConnectionBadRequest`, `ConfigCharacterIdMissing`）在调用处不可见。

| 条件                      | 消息（调用处的代码始终为 `ConnectionFailed`)                                                                                                                                                                                                                                             |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 注册的角色超过 50 个            | `Convai 房间最多支持 50 个角色，而此处请求的是 <count> 个。此 API 密钥对应的 Convai 套餐可能允许的数量更少；请在 Convai Manager > Characters Joining the Room 中仅发送此对话所需的角色。`                                                                                                                                        |
| 空或重复的角色引用               | `多角色名册包含空或重复的角色引用。`                                                                                                                                                                                                                                                          |
| 两个角色解析为相同的 Character ID | `“<name>” 和 “<name>” 都使用 Character ID <id>。同一个房间中的两个角色不能共享同一个 ID——SDK 会根据该 ID 路由所有权、参与者和音频，因此它们会发生冲突，而不是分别得到回应。请从 Convai 仪表板为每个角色分配各自的 Character ID。` 参见 [角色身份](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/character-identity.md). |
| 没有 Character ID 的角色     | `多角色房间中的每个角色都需要一个 Character ID。`                                                                                                                                                                                                                                             |
| 两个角色解析为相同的角色会话 ID       | `角色会话 ID 在多角色名册中必须唯一。`                                                                                                                                                                                                                                                       |

此验证仅在连接时构建名册时运行。 `JoinMultiCharacterRoomAsync` 不发送名册，因此不会引发这些异常。

***

### `MultiCharacterJoinOptions`

`MultiCharacterJoinOptions` 是传递给 `JoinMultiCharacterRoomAsync`的可序列化类。定义于 `SDK/Runtime/Room/TurnTakingOptions.cs:411-439`.

| 字段                 | 类型                                    | 默认                                           | 说明                                                                                                               |
| ------------------ | ------------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `房间会话 ID`          | `字符串`                                 | `null`                                       | 创建客户端的 connect 调用返回的持久房间标识符。请使用此项或 `SharedSessionKey`，不要同时使用两者。                                                  |
| `SharedSessionKey` | `字符串`                                 | `null`                                       | 房间的另一种由开发者控制的定位符。请使用此项或 `房间会话 ID`，不要同时使用两者。                                                                      |
| `EndUserId`        | `字符串`                                 | `null`                                       | 加入玩家的稳定开发者标识符。                                                                                                   |
| `EndUserMetadata`  | `IReadOnlyDictionary<string, object>` | `null`                                       | 终端用户的附加元数据。                                                                                                      |
| `TurnTaking`       | `TurnTakingOptions`                   | `TurnTakingOptions.CreateHandsFreeDefault()` | 加入参与者的轮流发言配置。参见 [轮流发言模式](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/turn-taking-modes.md). |

加入时会将这些字段转换为一个 `RoomSessionConnectOptions` 与 `JoinExistingMultiCharacterRoom` 设置为 `是` 并发送连接模式 `加入` ，且不带角色名册。

***

### `RoomSessionConnectOptions` — 多角色字段

`RoomSessionConnectOptions` 是 `ConnectAsync(RoomSessionConnectOptions, CancellationToken)`的可序列化类。定义于 `SDK/Runtime/Room/TurnTakingOptions.cs:329-358`。下表仅涵盖与多角色会话相关的字段；完整字段列表请参见 [ConvaiManager API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/convaimanager-api.md#roomsessionconnectoptions-fields) 。

| 字段                               | 类型    | 默认     | 说明                                                                   |
| -------------------------------- | ----- | ------ | -------------------------------------------------------------------- |
| `SharedSessionKey`               | `字符串` | `null` | 用于将多人参与者分组到同一房间中的可选共享会话密钥。                                           |
| `房间会话 ID`                        | `字符串` | `null` | 加入现有房间时使用的持久多角色房间标识符。请通过 `MultiCharacterJoinOptions` 进行正常使用，而不是直接设置。 |
| `JoinExistingMultiCharacterRoom` | `布尔值` | `否`    | 选择一种无需拓扑的人类加入方式，而不是构建并发送名册。                                          |
| `MaxNumParticipants`             | `整数`  | `0`    | 共享会话的可选最大参与者数量。                                                      |

***

### 相关参考

{% content-ref url="/pages/f4a7ab842bf490bd88b4adbd8fbf66d1757f124e" %}
[房间会话参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/room-session-reference.md)
{% endcontent-ref %}

{% content-ref url="/pages/1de47e20d64086de6ea2148c4871a665eec92182" %}
[多角色会话工作原理](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/how-multi-character-sessions-work.md)
{% endcontent-ref %}

{% content-ref url="/pages/a6e9c177aa5c598a856889f7e4baf09e8b838a4d" %}
[构建你的第一个多角色会话](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/quick-start.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/multi-character-sessions/connection-api-reference.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.
