> 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 的任务上处理该异常。

#### 每个操作共有的前提条件

| 条件                    | 异常                          | Message               |
| --------------------- | --------------------------- | --------------------- |
| 没有活动的多字符房间            | `InvalidOperationException` | `没有活动的多字符房间会话。`       |
| 命令在其闸门上等待时，多字符房间发生了变化 | `InvalidOperationException` | `此更新等待期间，多字符房间发生了变化。` |
| 房间数据通道尚未就绪            | `InvalidOperationException` | `房间数据通道尚未就绪。`         |

#### `JoinMultiCharacterRoomAsync`

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

`JoinMultiCharacterRoomAsync` 会转换为 `options` 连接到一个 `RoomSessionConnectOptions` 使用 `JoinExistingMultiCharacterRoom` 设置为 `true`，然后调用与 `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。两者共享相同的超时和确认失败行为；只有“非成员”检查因参数而异。

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

#### `ClearInteractionTargetAsync`

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

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

#### `AddCharacterAsync`

| 条件                         | 异常                               | Message                                                                                                                                                                                           |
| -------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `角色` 是 `null`              | `ArgumentNullException`          | —（`角色`)                                                                                                                                                                                           |
| `character.CharacterId` 为空 | `ArgumentException`              | `该角色必须具有角色 ID。` (`角色`)                                                                                                                                                                            |
| 本地角色实例已经是房间的成员             | `ArgumentException`              | `此本地角色实例已是当前房间的成员。添加克隆时请使用另一个实例。` (`角色`)                                                                                                                                                          |
| 当此命令在闸门上等待时，同一本地角色被添加      | `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`。两者共享替换目标和闸门竞争检查；只有“非成员”检查因参数而异。

| 条件                                          | 异常                               | Message                                               |
| ------------------------------------------- | -------------------------------- | ----------------------------------------------------- |
| 字符重载的 `角色` 是 `null`                         | `ArgumentNullException`          | —（`角色`)                                               |
| 成员 ID 重载的 `membershipId` 不是当前房间的一部分         | `ArgumentException`              | `该成员不属于当前房间。` (`membershipId`)                        |
| 字符重载的 `角色` 不是当前房间的成员                        | `ArgumentException`              | `该字符不是当前房间的成员。` (`角色`)                                |
| `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 会通过它路由所有权、参与者和音频，因此它们会发生冲突，而不是分别得到回应。请从 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`.

| 字段                 | 类型                                    | 默认                                           | 说明                                                                                                                |
| ------------------ | ------------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `RoomSessionId`    | `string`                              | `null`                                       | 创建客户端连接调用返回的持久房间标识符。使用此项或 `SharedSessionKey`，不要同时使用二者。                                                            |
| `SharedSessionKey` | `string`                              | `null`                                       | 房间的另一种、由开发者控制的定位符。使用此项或 `RoomSessionId`，不要同时使用二者。                                                                 |
| `EndUserId`        | `string`                              | `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` 设置为 `true` 并发送连接模式 `加入` ，且不带角色名册。

***

### `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`               | `string` | `null`  | 用于将多人参与者分组到同一房间的可选共享会话密钥。                                          |
| `RoomSessionId`                  | `string` | `null`  | 用于加入现有房间的持久多字符房间标识符。通过 `MultiCharacterJoinOptions` 进行常规使用，而不是直接设置。 |
| `JoinExistingMultiCharacterRoom` | `bool`   | `false` | 选择无拓扑的人类加入，而不是构建并发送名册。                                             |
| `MaxNumParticipants`             | `int`    | `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 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/multi-character-sessions/connection-api-reference.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.
