> 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/scripting-reference/convaimanager-api.md).

# ConvaiManager API

场景管理器组件的每个公共成员，涵盖连接控制、外观访问、玩家正在与谁交谈以及服务发现。

`ConvaiManager` 是 Convai Unity SDK 的主要脚本入口点。它初始化运行时，管理房间连接，拥有 `事件`, `音频`，以及 `转录` 门面，并通过类型化访问器授予对更低级服务的访问权限。每一次脚本交互都从这里开始。

**访问：** `ConvaiManager.ActiveManager` （单例）

```csharp
var manager = ConvaiManager.ActiveManager;
if (manager == null)
{
    Debug.LogError("场景中未找到 ConvaiManager。请通过 GameObject > Convai > Setup Required Components 添加它。");
    return;
}
```

{% hint style="warning" %}
`ActiveManager` 返回 `null` 如果不存在 `ConvaiManager` 于场景中，或者它尚未完成引导。使用前务必检查 null，尤其是在可能 `OnEnable` 在管理器初始化之前。
{% endhint %}

***

### 状态属性

| 属性               | 类型     | 说明                               |
| ---------------- | ------ | -------------------------------- |
| `IsBootstrapped` | `bool` | 静态。当运行时已完成初始引导时为 True——可以安全访问门面。 |
| `IsInitialized`  | `bool` | 当引导完成且事件中心可用时为 True。             |
| `IsConnected`    | `bool` | 当房间会话处于 `已连接` 状态时为 True。         |

***

### 门面访问器

| 属性   | 类型                  | 引用                                                                                                                                                                                                   |
| ---- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `事件` | `ConvaiEvents`      | [会话事件](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/session-events.md), [角色事件](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/character-events.md) |
| `音频` | `ConvaiAudio`       | [音频 API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/audio-api.md)                                                                                                        |
| `转录` | `ConvaiTranscripts` | [转录 API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/transcript-api.md)                                                                                                   |

***

### 所有权属性

| 属性                            | 类型                               | 说明                                |
| ----------------------------- | -------------------------------- | --------------------------------- |
| `角色`                          | `IReadOnlyList<ConvaiCharacter>` | 全部 `ConvaiCharacter` 当前由此管理器拥有的实例 |
| `Player`                      | `ConvaiPlayer`                   | 该 `ConvaiPlayer` 由此管理器拥有的实例       |
| `ActiveConversationCharacter` | `ConvaiCharacter`                | 当前被设为对话目标的角色；可能是 `null`           |
| `ConversationMode`            | `ConvaiManagerConversationMode`  | 此管理器配置的对话模式                       |
| `ActiveConversationInputMode` | `ConversationInputMode`          | 当前生效的运行时对话输入模式                    |
| `PushToTalkKey`               | `KeyCode`                        | 用于按键发言的按键代码，当模式为 `PushToTalk`     |

### `ConvaiManagerConversationMode` 枚举

| 值                     | 说明                                     |
| --------------------- | -------------------------------------- |
| `UseRoomDefaults` (0) | 使用中配置的对话输入模式 `TurnTakingOptions` 在管理器上 |
| `HandsFree` (1)       | 设置免提（LocalAudio）模式，覆盖房间默认值             |
| `PushToTalk` (2)      | 设置按键发言模式，覆盖房间默认值                       |

***

### 房间操作

### `ConnectAsync`

```csharp
// 简单连接——使用场景配置
IConvaiOperation<RoomSession> ConnectAsync(CancellationToken ct = default)

// 使用运行时覆盖项连接
IConvaiOperation<RoomSession> ConnectAsync(RoomSessionConnectOptions options, CancellationToken ct = default)
```

返回一个 `RoomSession` 成功时。参见 [操作与流类型](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/operation-and-stream-types.md) 和 [异步模式](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/async-patterns.md) 了解使用模式。

#### `RoomSessionConnectOptions` 字段

将其传递给第二个重载，以在连接时覆盖运行时行为。

| 字段                               | 类型                                    | 说明                                                                                                                                                         |
| -------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TurnTaking`                     | `TurnTakingOptions`                   | 覆盖此会话的轮流发言配置。参见 [轮流发言模式](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/core-concepts/turn-taking-modes.md) 完整字段参考。                                    |
| `EndUserId`                      | `string`                              | 覆盖此会话的最终用户 ID（用于长期记忆）                                                                                                                                      |
| `CharacterSessionId`             | `string`                              | 可选会话 ID，限定于此次显式最终用户连接请求。若存在最终用户 ID，请优先使用它，而不是角色自己的 `ConvaiCharacter.CharacterSessionId` 字段。                                                                |
| `EndUserMetadata`                | `IReadOnlyDictionary<string, object>` | 用于最终用户的附加元数据                                                                                                                                               |
| `ActionConfigOverride`           | `ConvaiActionConfig`                  | 覆盖此会话的动作配置                                                                                                                                                 |
| `ActionDefinitionsOverride`      | `List<ConvaiActionDefinition>`        | 覆盖为此会话注册的动作定义                                                                                                                                              |
| `SharedSessionKey`               | `string`                              | 用于将多人参与者分组到同一房间的可选共享会话密钥。参见 [连接 API 参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/connection-api-reference.md). |
| `RoomSessionId`                  | `string`                              | 用于加入现有房间的持久多字符房间标识符。通过 `MultiCharacterJoinOptions` 进行常规使用，而不是直接设置。                                                                                         |
| `JoinExistingMultiCharacterRoom` | `bool`                                | 选择无拓扑的人类加入，而不是构建并发送名册。                                                                                                                                     |
| `MaxNumParticipants`             | `int`                                 | 共享会话的可选最大参与者数量。                                                                                                                                            |

```csharp
var options = new RoomSessionConnectOptions
{
    EndUserId = currentUser.Id,
    EndUserMetadata = new Dictionary<string, object>
    {
        ["department"] = "Engineering",
        ["cohort"]     = "2025-Q2"
    }
};

var result = await manager.ConnectAsync(options, destroyCancellationToken);
if (!result.IsSuccessful)
    Debug.LogError($"连接失败：{result.Error.Message}");
```

### `DisconnectAsync`

```csharp
IConvaiOperation<Unit> DisconnectAsync(CancellationToken ct = default)
```

优雅地断开房间会话。会在会话到达时完成 `Disconnected`.

***

### 对话控制

| 方法                                                                                          | 返回                       | 说明                                                                |
| ------------------------------------------------------------------------------------------- | ------------------------ | ----------------------------------------------------------------- |
| `SetConversationInputModeAsync(ConversationInputMode mode, CancellationToken ct = default)` | `IConvaiOperation<Unit>` | 在运行时切换房间的对话输入模式                                                   |
| `StartListening()`                                                                          | `void`                   | 开始麦克风采集。是以下方法的快捷方式 `Audio.StartListeningAsync()` 并使用默认设备。         |
| `ToggleMicMute()`                                                                           | `bool`                   | 切换麦克风静音。返回新的静音状态。                                                 |
| `EnableAudioAndStartListening()`                                                            | `void`                   | 调用 `Audio.EnableAudioPlayback()` 然后开始监听。在 WebGL 上进行任何音频交互之前这是必需的。 |

***

### 直接 C# 事件

`ConvaiManager` 除了可通过以下方式访问的类型化中心外，还公开三个直接 C# 事件 `事件`。当你需要轻量级的会话状态通知，而不想使用完整的事件中心或转发器设置时，请订阅这些事件。

| 事件               | 签名                     | 触发时机                |
| ---------------- | ---------------------- | ------------------- |
| `OnConnected`    | `操作`                   | 会话到达 `已连接`          |
| `OnDisconnected` | `操作`                   | 会话到达 `Disconnected` |
| `OnError`        | `Action<SessionError>` | 会话遇到错误              |

若要获取更丰富的会话状态数据（转换上下文、参与者变更、空闲警告），请使用 `ConvaiSessionEventRelay` 或 `ConvaiManager.ActiveManager.Events`。上面的直接事件故意保持最简——仅包含连接和错误。

***

### 所有权管理

使用这些方法和属性来控制管理器拥有哪些角色和玩家、哪些角色加入下一次房间连接，以及房间以哪个角色开始。

| 成员                                                                | 说明                                                                                                                                                                  |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SetInitialCharacter(ConvaiCharacter character)`                  | 选择房间连接时第一个发言的角色。这是初始化设置，不是运行中的切换——它决定对话从哪里开始；在已连接的房间中修改它会排队重新连接，而不会移动对话。保持未设置是正常的：场景顺序中的第一个角色会先发言。若要在实时房间中切换对话，请使用 `TalkTo`.                                        |
| `InitialCharacter`                                                | `ConvaiCharacter`. 的读取部分 `SetInitialCharacter`. `null` 在尚未显式选择时。                                                                                                    |
| `TalkTo(ConvaiCharacter character)`                               | 将对话指向实时多角色房间中的某一个角色。任何时候调用都安全；当房间不是多角色房间或该角色不在房间中时不会产生任何效果。参见 [对话目标定位](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/conversation-targeting.md).      |
| `AddressedCharacter`                                              | `ConvaiCharacter`. 当前玩家正在与之交谈的角色；在房间存在之前和之后都会解析。将聊天字段标签绑定到这里，而不要绑定到玩家碰巧正在看的对象。                                                                                      |
| `ConversationAvailability`                                        | `ConvaiConversationAvailability`. 玩家当前是否可以与 `AddressedCharacter` 交谈。值： `无角色`, `离线`, `连接中`, `Preparing`, `Ready`, `Answering`, `Unavailable`.                        |
| `ConversationAvailability.CanAcceptPlayerInput()`                 | 上的扩展方法 `ConvaiConversationAvailability`。返回 `true` 当值为 `Ready` 或 `Answering` —— 这两个状态才接受消息。聊天字段和麦克风按钮应基于此进行门控，而不是基于 `IsConnected`.                                   |
| `ConversationTargeting`                                           | `ConversationTargetingOptions`. 自动对话目标定位的调优项（模式、范围、视角、切换边距、切换延迟）。不要 `null`.                                                                                         |
| `SetCharactersToConnect(IEnumerable<ConvaiCharacter> characters)` | 选择下一次房间连接中包含的确切拥有角色集合，替换任何先前的选择。传入空集合会刻意让下一次连接没有有效的角色列表。更改会应用于下一次连接，而不是当前连接。                                                                                        |
| `CharactersToConnect`                                             | `IReadOnlyList<ConvaiCharacter>`. 由以下方法设置的显式房间选择集 `SetCharactersToConnect`，或者在包含所有活动角色时为空。该选择是一个确切集合，而不是可追加的列表——在调用之前先阅读这一点 `SetCharactersToConnect` 如果你的意思是“以及这个”。 |
| `UseAllCharactersForConnection()`                                 | 恢复默认行为：下次房间连接会包含每个已拥有、处于活动场景中的角色。                                                                                                                                   |
| `SetExplicitPlayer(ConvaiPlayer player)`                          | 分配一个特定的 `ConvaiPlayer` 实例作为受管理的玩家                                                                                                                                   |
| `SetExplicitCharacters(IEnumerable<ConvaiCharacter> characters)`  | 用提供的集合替换受管理的角色列表                                                                                                                                                    |
| `RefreshReferences()`                                             | 重新扫描场景中的 `ConvaiCharacter` 和 `ConvaiPlayer` 实例以重建受管理集合                                                                                                              |

#### 运行时生成的角色

在场景加载后实例化的角色，在 `Instantiate` 返回的瞬间并不可用。管理器必须先取得它的所有权并注入服务，这会在后续帧中发生。 `ConvaiCharacter.IsInjected` 会报告这一过程何时完成，而在完成之前，该角色的对话和音频调用都不会生效。

生成角色后，调用 `RefreshReferences()` —— 或者 `SetExplicitCharacters` 如果管理器没有自动扫描场景的话——然后等待 `IsInjected` 之后再与其交谈。

```csharp
using System;
using System.Threading.Tasks;
using Convai.Runtime.Components;
using UnityEngine;

public static class RuntimeCharacterSpawn
{
    public static async Task<ConvaiCharacter> SpawnAsync(GameObject prefab, Vector3 position)
    {
        ConvaiCharacter character = UnityEngine.Object
            .Instantiate(prefab, position, Quaternion.identity)
            .GetComponent<ConvaiCharacter>();

        ConvaiManager.ActiveManager.RefreshReferences();

        for (int frame = 0; frame < 120; frame++)
        {
            if (character != null && character.IsInjected) return character;
            await Task.Yield();
        }

        throw new InvalidOperationException(
            "未注入运行时角色。请确保场景中存在一个活动的 ConvaiManager。");
    }
}
```

SDK 在共享示例中将此模式作为 `RuntimeCharacterSpawner` 提供。

***

### 服务访问器模式

对于需要直接访问内部服务的高级场景， `ConvaiManager` 公开了 12 个类型化的 `TryGet*` 访问器。每个都返回 `true` ，并在成功时设置 `输出` 参数，或者在服务不可用时返回 `false` 。

{% hint style="info" %}
常见任务优先使用 `事件`, `音频`，以及 `转录` 门面属性。 `TryGet*` 这些访问器面向高级集成和自定义工具。
{% endhint %}

```csharp
if (manager.TryGetMicrophoneDeviceService(out var micService))
{
    var devices = micService.GetAvailableDevices();
    // 填充设备选择器 UI
}
```

| 方法                                                                  | 服务类型                             | 常见用途                                                                                                                                      |
| ------------------------------------------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `TryGetEventHub(out IEventHub)`                                     | `IEventHub`                      | 通过以下方式直接访问原始事件总线 `ConvaiEvents.Raw`；高级订阅                                                                                                  |
| `TryGetRoomConnectionService(out IConvaiRoomConnectionService)`     | `IConvaiRoomConnectionService`   | 底层连接生命周期控制，包括 [多角色会话操作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/multi-character-sessions/connection-api-reference.md) |
| `TryGetRoomAudioService(out IConvaiRoomAudioService)`               | `IConvaiRoomAudioService`        | 直接音频服务访问（绕过 `ConvaiAudio` 门面）                                                                                                             |
| `TryGetAgentRegistry(out IAgentRegistry)`                           | `IAgentRegistry`                 | 查询已注册的角色和玩家                                                                                                                               |
| `TryGetSettingsPanelController(out IConvaiSettingsPanelController)` | `IConvaiSettingsPanelController` | 以编程方式打开/关闭设置面板                                                                                                                            |
| `TryGetRuntimeSettingsService(out IConvaiRuntimeSettingsService)`   | `IConvaiRuntimeSettingsService`  | 读取和写入运行时设置（音频音量、麦克风设备等）                                                                                                                   |
| `TryGetMicrophoneDeviceService(out IMicrophoneDeviceService)`       | `IMicrophoneDeviceService`       | 枚举可用的麦克风设备；构建设备选择器 UI                                                                                                                     |
| `TryGetPermissionService(out IConvaiPermissionService)`             | `IConvaiPermissionService`       | 请求平台麦克风权限（Android、iOS）                                                                                                                    |
| `TryGetNotificationService(out IConvaiNotificationService)`         | `IConvaiNotificationService`     | 从你自己的脚本触发 SDK 通知                                                                                                                          |
| `TryGetPlayerInputService(out IPlayerInputService)`                 | `IPlayerInputService`            | 访问玩家输入状态和文本消息路由                                                                                                                           |
| `TryGetVisibleCharacterService(out IVisibleCharacterService)`       | `IVisibleCharacterService`       | 维护由你自己的可见性逻辑通过以下方式添加的角色 ID 集合 `AddCharacter`/`RemoveCharacter`；由转录 UI 用于过滤和淡出                                                             |
| `TryGetTransportProvider(out ITransportProvider)`                   | `ITransportProvider`             | 访问传输层，用于诊断或自定义传输场景                                                                                                                        |

***

### SDK 版本

该 `ConvaiSDK` 静态类公开 SDK 版本，以便进行条件特性检查。

```csharp
using Convai.Application;

Debug.Log($"Convai SDK {ConvaiSDK.Version}");

// 将其设置为你的集成所支持的最低 SDK 版本。
const string MinimumSupportedVersion = "4.6.0";

if (ConvaiSDK.Version >= System.Version.Parse(MinimumSupportedVersion))
{
    // 可以安全使用该版本提供的 API
}
```

***

### 使用示例

### 示例 1 — 在场景加载时带取消功能连接

一个工业安全模拟在场景加载时连接到 Convai，并通过 `destroyCancellationToken` 将连接操作绑定到组件生命周期，这样如果场景在尝试过程中卸载，连接就会干净地取消。

{% code title="SceneConnector.cs" %}

```csharp
using Convai.Runtime.Core.Async;
using Convai.Runtime.Facades;
using UnityEngine;

public class SceneConnector : MonoBehaviour
{
    private async void Start()
    {
        var manager = ConvaiManager.ActiveManager;
        if (manager == null) return;

        try
        {
            var session = await manager.ConnectAsync(destroyCancellationToken);
            Debug.Log($"已连接。会话：{session.RoomId}");
        }
        catch (ConvaiOperationException ex)
        {
            Debug.LogError($"连接失败：{ex.Message}");
        }
        catch (System.OperationCanceledException) { /* 场景已卸载 */ }
    }
}
```

{% endcode %}

### 示例 2 — 在触发区域进入时切换对话

一个企业入职模拟在房间里有多个 AI 顾问。当学习者走进某个顾问的区域时，对话会切换到该顾问，并使用 `TalkTo`.

{% code title="AdvisorZone.cs" %}

```csharp
using Convai.Runtime.Components;
using Convai.Runtime.Facades;
using UnityEngine;

public class AdvisorZone : MonoBehaviour
{
    [SerializeField] private ConvaiCharacter _advisor;

    private void OnTriggerEnter(Collider other)
    {
        if (!other.CompareTag("Player")) return;
        ConvaiManager.ActiveManager?.TalkTo(_advisor);
    }
}
```

{% endcode %}

### 示例 3 — 麦克风设备选择器 UI

一种交互式体验允许用户在会话开始前选择自己偏好的麦克风，使用 `IMicrophoneDeviceService` 来枚举可用设备。

{% code title="MicrophonePicker.cs" %}

```csharp
using Convai.Runtime.Facades;
using System.Linq;
using TMPro;
using UnityEngine;

public class MicrophonePicker : MonoBehaviour
{
    [SerializeField] private TMP_Dropdown _deviceDropdown;

    private void Start()
    {
        var manager = ConvaiManager.ActiveManager;
        if (manager == null || !manager.TryGetMicrophoneDeviceService(out var micService))
            return;

        var devices = micService.GetAvailableDevices();
        _deviceDropdown.ClearOptions();
        _deviceDropdown.AddOptions(devices.Select(d => d.Name).ToList());
    }
}
```

{% endcode %}

***

### 故障排除

| 症状                             | 可能原因                                   | 修复方法                                                                                                                    |
| ------------------------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `ActiveManager` 返回 `null` 在运行时 | `ConvaiManager` 不在场景中，或在引导完成前访问        | 通过以下方式添加 **GameObject > Convai > Setup Required Components**；使用前检查 null；订阅 `OnConnected` 而不是在中读取状态 `Awake` 或 `OnEnable` |
| `TryGet*` 返回 `false`           | 服务不可用或管理器尚未完全引导                        | 检查 `IsBootstrapped` 在调用之前；在之后调用 `OnConnected` 触发                                                                        |
| `ConnectAsync` 保持 `运行中` 无限期    | API 密钥无效、网络不可达，或 `ConvaiSettings` 资源缺失 | 在以下位置验证 API 密钥 **Convai → Settings**；使用超时 `CancellationToken` 来暴露失败                                                     |
| `RefreshReferences` 未找到动态生成的角色 | 在场景加载后实例化的角色不会被自动发现                    | 调用 `RefreshReferences()` 在实例化后，或使用 `SetExplicitCharacters()` 直接注册它们                                                     |

***

### 下一步

有关音频和麦克风脚本，请参见 [音频 API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/audio-api.md)。有关 C# 中的连接状态和错误事件，请参见 [会话事件](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/session-events.md)。有关异步操作消费模式，请参见 [异步模式](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/async-patterns.md).


---

# 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/scripting-reference/convaimanager-api.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.
