> 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/join-an-existing-session.md).

# 加入现有房间

使用恰好一个房间定位器，将另一位人类参与者带入另一个客户端已创建的 Unity 多角色房间。

使用一个已存在房间，将第二位人类参与者带入其中 `JoinMultiCharacterRoomAsync`，且只使用一个房间定位器。 当配套客户端需要加入另一个客户端已经创建的会话，而不是创建新的名册时，请使用此页面。

### 前置条件

* 由另一个客户端已创建的多角色会话，以及其 `RoomSessionId` 或 `SharedSessionKey` 可供加入的客户端使用。
* `IConvaiRoomConnectionService`，通过以下方式获取 `ConvaiManager.TryGetRoomConnectionService`.
* 一个不同的 `EndUserId` 用于加入的参与者。

### 加入房间

调用 `JoinMultiCharacterRoomAsync(MultiCharacterJoinOptions options, CancellationToken cancellationToken = default)`。在底层，它会构建一个 `RoomSessionConnectOptions` 使用 `JoinExistingMultiCharacterRoom` 已设置，因此不会发送名册——加入操作会重用创建客户端已建立的名册。

| `MultiCharacterJoinOptions` 字段 | 用于                              |
| ------------------------------ | ------------------------------- |
| `RoomSessionId`                | 返回给创建客户端的持久房间标识符 `/connect` 调用。 |
| `SharedSessionKey`             | 同一房间的另一种由开发者控制的定位器。             |
| `EndUserId`                    | 用于加入参与者的稳定标识符。                  |
| `EndUserMetadata`              | 用于加入参与者的可选键值元数据。                |
| `TurnTaking`                   | 该参与者会话的轮流选项；默认是免手动。             |

设置 `RoomSessionId` 或 `SharedSessionKey`，而不是两者都用——房间每次加入请求只接受一个定位器。加入不需要一个处于活动状态的角色，也不需要调用 `SetInitialCharacter`；当 `JoinExistingMultiCharacterRoom` 已设置。

{% code title="Assets/Scripts/JoinExistingSessionBootstrap.cs" %}

```csharp
using System;
using System.Threading;
using Convai.Runtime.Core.Async;
using Convai.Runtime.Room;
using UnityEngine;

public class JoinExistingSessionBootstrap : MonoBehaviour
{
    [SerializeField] private string _roomSessionId;
    [SerializeField] private string _endUserId;

    private readonly CancellationTokenSource _lifetime = new();

    private async void Start()
    {
        ConvaiManager manager = ConvaiManager.ActiveManager;
        if (manager == null || !manager.TryGetRoomConnectionService(out IConvaiRoomConnectionService roomService))
        {
            Debug.LogError("[MultiCharacter] 在加入房间之前，请先向场景中添加一个 ConvaiManager。");
            return;
        }

        var joinOptions = new MultiCharacterJoinOptions
        {
            RoomSessionId = _roomSessionId,
            EndUserId = _endUserId
        };

        try
        {
            await roomService.JoinMultiCharacterRoomAsync(joinOptions, _lifetime.Token);
        }
        catch (ConvaiOperationException error)
        {
            Debug.LogError($"[MultiCharacter] 加入失败 ({error.Code}): {error.Message}");
            return;
        }
        catch (ArgumentNullException error)
        {
            Debug.LogError($"[MultiCharacter] {error.Message}");
            return;
        }
        catch (OperationCanceledException)
        {
            return;
        }

        MultiCharacterRoomSession session = roomService.CurrentMultiCharacterSession;
        if (session == null)
        {
            Debug.LogWarning("[MultiCharacter] 已加入，但未返回多角色会话。");
            return;
        }

        Debug.Log($"[MultiCharacter] 已加入房间 {session.RoomSessionId}，共有 {session.Characters.Count} 个角色。");
    }

    private void OnDestroy()
    {
        _lifetime.Cancel();
        _lifetime.Dispose();
    }
}
```

{% endcode %}

### 验证加入

在将输入路由自加入客户端之前，请先在控制台中确认以下两点。

* `CurrentMultiCharacterSession` 不是 `null`，以及 `RoomSessionId` 与您打算加入的房间相匹配。
* `session.Characters` 报告与创建客户端看到的相同名册。没有本地 `ConvaiCharacter` 绑定到它在这里是正常的——加入场景不需要拥有房间中的每个角色。

### 故障排除

| 症状                                           | 原因                           | 修复方法                                                                           |
| -------------------------------------------- | ---------------------------- | ------------------------------------------------------------------------------ |
| 加入失败，返回一个 `ConvaiOperationException`         | 房间定位器缺失或重复，或者该账户无法访问该房间。     | 只发送 `RoomSessionId` 或 `SharedSessionKey`，而不是两者都发送，并确认该值。Convai 会在异常中报告原因 `代码`. |
| `CurrentMultiCharacterSession` 是 `null` 在加入后 | 您加入的房间没有可公开的名册，这只会发生在单角色房间中。 | 确认目标房间是作为多角色会话创建的。                                                             |

参见 [使用多角色会话](/api-docs/zh/api-can-kao/core-api-reference/live-apis-beta/multi-character-sessions.md#verify-and-troubleshoot) 请参见协议级加入失败表。

### 下一步

{% content-ref url="/pages/d8451a87588c6ea22a959d1a3ecd7ecc09422e8a" %}
[对话目标选择](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/conversation-targeting.md)
{% endcontent-ref %}

{% content-ref url="/pages/adffcd7e333fbd7f83aafb6f96412854dcf886f5" %}
[角色加入与离开](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/update-the-roster.md)
{% endcontent-ref %}

{% content-ref url="/pages/83bfde40c2f58faadfb576aa1fa7ea38a47d20fe" %}
[使用多角色会话](/api-docs/zh/api-can-kao/core-api-reference/live-apis-beta/multi-character-sessions.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/join-an-existing-session.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.
