> 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/troubleshooting.md).

# 排查多角色会话问题

在 Unity 中运行多角色会话时，修复成员列表拒绝、就绪失败、音频路由错误和命令错误。

大多数多角色问题都出在三个地方之一：SDK 在连接时构建的名册、运行时用于定位成员身份的标识，或一个 `IConvaiOperation<T>` 会失败而不是完成的命令。请在下方找到准确的消息或症状；每一项都引用了其在 Unity Console 中显示的文本，并在只引用较长一行开头时明确说明。

### 开始之前

* 确认 `IConvaiRoomConnectionService.CurrentMultiCharacterSession` 不是 `null` 在诊断其他任何问题之前——下方的若干症状仅在多角色会话存在后才适用。
* 请阅读失败发生时的 Console 行。以下消息均为逐字引用，匹配错项会导致错误的修复。
* 确认场景中有两个或更多 **处于激活且启用状态的** `ConvaiCharacter` 组件后再连接。非激活或已禁用的角色会被静默排除在名册之外，而单个激活角色永远不会生成名册。

### 在没有激活角色时连接失败

在构建任何名册之前都会先运行一个单独的检查，无论场景中有多少角色。

| 症状                                              | 原因                                                                                                                        | 修复                                                                              | 验证           |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------ |
| `ConvaiOperationException`: `无法连接，因为没有可用的激活角色。` | 在……时未解析到任何激活角色 `ConnectAsync` 运行——例如，所有所属角色都处于非激活或已禁用状态。不适用于 `JoinMultiCharacterRoomAsync`，它不需要激活角色，因为它加入的是另一个客户端已经创建的房间。 | 至少激活一个 `ConvaiCharacter`，或者调用 `ConvaiManager.SetInitialCharacter` 带有激活角色，然后再连接。 | 连接尝试不再抛出此消息。 |

### 连接时名册被拒绝

当其名册违反以下规则之一时，拥有两个或更多激活、启用角色的场景会在任何请求到达 Convai 之前被拒绝。非激活或已禁用的 `ConvaiCharacter` 会在这些规则运行前被排除出名册，因此不可能触发其中任何一条。

| 症状                                                                     | 原因                                                                    | 修复                                                                                                                                                          | 验证                                                          |
| ---------------------------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `ConvaiOperationException`：消息开头 `一个 Convai 房间最多支持 50 个角色`              | 超过 50 个处于激活且启用状态的 `ConvaiCharacter` 组件已注册到管理器。                        | 将激活角色数量减少到 50 个或更少，或使用 **Convai Manager > Characters Joining the Room** 只发送此对话所需的角色。                                                                        | 连接尝试不再抛出，而且 `CurrentMultiCharacterSession` 会被填充。            |
| `ConvaiOperationException`: `多角色名册包含空引用或重复的角色引用。`                      | 同样的 `ConvaiCharacter` 组件被注册了两次，或者有空引用传到了名册构建器。                        | 每个组件只注册一次。使用第二个组件实例来添加同一角色的克隆。                                                                                                                              | `session.Characters` 对于每个不同的 `ConvaiCharacter` 实例，恰好保留一个成员。 |
| `ConvaiOperationException`：消息开头 `'<name>' 和 '<name>' 都使用 Character ID` | 两个激活且启用的角色共享同一个 Character ID——通常是因为其中一个是从另一个复制出来的。                    | 请在 Convai 仪表板中为副本分配它自己的 Character ID。参见 [角色身份](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/character-identity.md). | 连接尝试不再抛出此消息。                                                |
| `ConvaiOperationException`: `多角色房间中的每个角色都需要一个 Character ID。`           | 场景中一个激活且启用的 `ConvaiCharacter` 具有空的 **角色 ID** 字段从其他 GameObject 分配一个角色。 | 请为场景中每个激活角色设置该字段，并在你之后激活并通过以下方式添加任何非激活角色之前先设置好： `AddCharacterAsync`.                                                                                        | 连接尝试不再抛出此消息。                                                |
| `ConvaiOperationException`: `角色会话 ID 在多角色名册中必须唯一。`                     | 两个角色解析到了相同的角色会话 ID。                                                   | 为每个实例分配不同的角色会话 ID，或者省略它，这样 SDK 会为该实例开始新的对话。                                                                                                                 | 连接尝试不再抛出此消息。                                                |

{% hint style="info" %}
该 `ConvaiOperationException` 因这四种条件中的任意一种而抛出的异常都携带上述完全相同的消息，但其 `代码` 始终是 `ConnectionFailed` 在调用点——原始会话错误代码在那里不可见。参见 [Connection API 参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/connection-api-reference.md#connect-time-roster-validation).
{% endhint %}

### 运行时和寻址问题

| 症状                                            | 原因                                                                                                                | 修复                                                                                                                                                                                                                                           | 验证                                                                     |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| 在运行时被启用的角色从不加入，而且不会抛出任何异常                     | 房间仅连接了一个激活角色，因此它是在没有可加入的名册的情况下打开的。Console 每次连接只警告一次： `'<'name'>' 不能加入此对话：该房间是为单个角色打开的，因此没有可加入的名册。下次房间连接时会将其包含进去。` | 让你希望在场景中处于激活状态的所有角色 **之前** 在房间连接之前完成，这样它就会带着可加入的名册打开。参见 [角色加入与离开](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/update-the-roster.md#a-single-character-room-cant-grow).                              | Console 会记录 `'<name>' 在未重新连接的情况下加入了房间。` 。                              |
| 我预期中的一个角色缺失于 `session.Characters`             | 该角色的 `GameObject` 或 `ConvaiCharacter` 当房间连接时，其组件处于非激活或已禁用状态。SDK 会静默地将非激活角色排除在启动名册之外——不会抛出异常，也不会有验证消息指出缺失的角色。      | 在连接前激活该角色，或者让它在运行时被启用时自动加入，或者使用以下方式显式添加它： [角色加入与离开](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/update-the-roster.md#add-a-character-to-the-roster).                                                | 该角色出现在 `session.Characters` 并带有一个 `MembershipId`.                      |
| 某个成员会一直保持 `启动中` 并且永远不会到达 `就绪`                 | Convai 尚未就该成员做出任何报告，或者其配置流程卡住了。                                                                                   | 订阅 `CharacterStatusChanged` 并检查 `ProvisioningStatus` 和 `FailureCode` 在该成员上。 `WaitUntilReadyAsync` 只报告初始角色；参见 [房间就绪](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/readiness-and-partial-dispatch.md). | 该成员的 `Status` 会变成 `就绪` 或 `Failed` 并带有一个 `FailureCode` 可供你采取行动的。        |
| 玩家输入到达了一个并非玩家意图中的角色                           | 代码缓存了一个过期的 `MembershipId`，或者在目标解析之后、输入发送之前，交互目标发生了变化。                                                             | 读取 `MultiCharacterRoomSession.ActiveMembershipId` 在处理输入之前立即读取，而不是缓存成员引用。                                                                                                                                                                     | 你的代码所定位的成员与 `ActiveMembershipId` 在发送输入时刻一致。                            |
| 同一角色的两个克隆被解析为一个对象，或者本应针对一个克隆的事件似乎同时影响了两个克隆    | 某个查找或音频映射以 `CharacterId`为键，而这在名册中并不唯一。                                                                            | 将查找的键改为 `MembershipId` 用于寻址，并用 `ParticipantIdentity` 用于音频。参见 [角色身份](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/character-identity.md).                                                             | 每个克隆的 `MembershipId` 和 `ParticipantIdentity` 以驱动不同的行为。                 |
| `CurrentMultiCharacterSession` 是 `null` 在连接之后 | 连接响应没有同时包含名册和房间会话 ID——对于单角色房间、没有返回多角色数据的连接，或者对于拥有两个角色但连接时只有一个处于激活且启用状态的场景来说，这是预期情况。                               | 确认场景中有两个或更多 **处于激活且启用状态的** `ConvaiCharacter` 组件后再连接。                                                                                                                                                                                         | `CurrentMultiCharacterSession` 不是 `null` 和 `Characters` 为每个激活角色保留一个成员。 |

### 名册和目标命令失败

在……上的每个操作 `IConvaiRoomConnectionService` 都会使其 `IConvaiOperation<T>` 出错而不是同步抛出——请在 await 的任务上处理异常。

| 症状                                                           | 原因                                                                             | 修复                                                       | 验证                                                                        |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------------------- |
| `CharacterRosterUpdateException` 代码为 `roster_epoch_mismatch` | 另一个已接受的名册命令先更改了名册。                                                             | 读取 `session.RosterEpoch` 并使用当前值重试该修改。                    | 重试调用完成且不会出现该异常。                                                           |
| `CharacterRosterUpdateException` 代码为 `unauthorized_sender`   | Convai 未接受该客户端作为有权更改房间名册的客户端。                                                  | 请确认该命令是从 Convai 识别为该房间的客户端发送的，然后重试。                      | 重试调用完成，名册反映出预期的更改。                                                        |
| `TimeoutException`: `等待角色名册更新确认超时。`                          | 在……之后 15 秒内未收到确认： `AddCharacterAsync` 或 `RemoveCharacterAsync`.                | 重新读取 `session.Characters` 后再重试——Convai 可能已经应用了该更改。       | `session.Characters` 反映出你预期的名册。                                           |
| `TimeoutException`: `等待交互目标确认超时。`                            | 在……之后 10 秒内未收到确认： `SetInteractionTargetAsync` 或 `ClearInteractionTargetAsync`. | 重新读取 `ActiveMembershipId` 和 `RouteEpoch` 后再重试。           | `ActiveMembershipId` 反映出你预期的目标。                                           |
| `ArgumentException`: `这个本地角色实例已经是当前房间的成员。在添加克隆时请使用另一个实例。`    | 同样的 `ConvaiCharacter` 组件实例被传给了 `AddCharacterAsync` 两次。                         | 请使用第二个 `ConvaiCharacter` 实例来添加克隆，而不是重复使用现有实例。            | `AddCharacterAsync` 会成功并在……中返回一个新的成员 `CharacterRosterUpdateResult.Added`. |
| `ArgumentException`: `替换目标不属于当前房间。`                          | 该 `replacementTargetMembershipId` 传递给 `RemoveCharacterAsync` 与当前任何成员都不匹配。      | 重新读取 `session.Characters` 并传入一个 `MembershipId` 当前位于名册中的。 | 调用完成，并且 `ActiveMembershipId` 反映出替换结果。                                     |
| `ArgumentException`: `替换目标不能是正在被移除的成员。`                      | `replacementTargetMembershipId` 等于传递给 `RemoveCharacterAsync`.                  | 请传入其他成员作为替换，或者在目标应被清除时省略它。                               | 调用完成且不会出现该异常。                                                             |

{% hint style="warning" %}
除……之外，后端可能还存在其他名册错误代码 `roster_epoch_mismatch` 和 `unauthorized_sender`。将客户端以前未见过的任何代码视为无法识别的后端拒绝，并同时记录 `CharacterRosterUpdateException.Code` 和 `消息` 而不是自行假设原因。
{% endhint %}

### 仍然受阻

在升级处理前，请收集以下信息：准确的 Console 消息、 `RoomSessionId` 受影响房间的，以及当前的 `RosterEpoch` 和 `RouteEpoch` 来自 `MultiCharacterRoomSession`，以及同一调用在一个新建房间中是否成功。请将该症状与以下内容交叉核对： [Live API 故障排查表](/api-docs/zh/api-can-kao/core-api-reference/live-apis-beta/multi-character-sessions.md#verify-and-troubleshoot) ——源自后端的拒绝也会出现在那里，并以协议级别进行描述。

### 相关页面

{% 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/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/634a0663b206a73fe4e2113edd3096e48b351d9a" %}
[连接 API 参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/connection-api-reference.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/troubleshooting.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.
