> 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`，使用恰好一个房间定位器。当需要让一个配套客户端加入另一个客户端已创建的会话，而不是创建新的名册时，请使用此页面。

### 前提条件

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

### 加入房间

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

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

设置 `房间会话 ID` 或 `SharedSessionKey`，而不是同时使用两者——每个加入请求只接受一个定位器。加入不需要激活角色，也不需要调用 `SetInitialCharacter`；当……时，SDK 会完全跳过该要求 `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`以及 `房间会话 ID` 与您打算加入的房间匹配。
* `session.Characters` 报告的名册与创建客户端看到的相同。没有本地 `ConvaiCharacter` 绑定到它在这里是正常的——加入场景不需要拥有房间中的每个角色。

### 故障排查

| 症状                                           | 原因                              | 修复方法                                                                       |
| -------------------------------------------- | ------------------------------- | -------------------------------------------------------------------------- |
| 加入失败，出现 `ConvaiOperationException`           | 缺少或重复的房间定位器，或者该账户无法访问该房间。       | 只发送恰好 `房间会话 ID` 或 `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 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/join-an-existing-session.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.
