> 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/character-and-player-api.md).

# 角色和玩家 API

`ConvaiCharacter` 控制单个 AI 角色的会话、语音、远程音频、动态上下文和注意力目标。 `ConvaiPlayer` 表示本地人类参与者，并提供文本消息发送和身份配置。这两个组件由……拥有并跟踪。 `ConvaiManager`.

***

### 访问组件

```csharp
// 通过 Inspector 字段（推荐）
[SerializeField] private ConvaiCharacter _character;

// 通过管理器所有权列表
var character = ConvaiManager.ActiveManager?.Characters[0];

// 通过管理器的活动对话目标
var active = ConvaiManager.ActiveManager?.ActiveConversationCharacter;

// 玩家
var player = ConvaiManager.ActiveManager?.Player;
```

***

### `ConvaiCharacter`

#### 属性

| 属性                                | 类型                       | 访问  | 描述                                       |
| --------------------------------- | ------------------------ | --- | ---------------------------------------- |
| `CharacterId`                     | `string`                 | 读取  | Convai 角色标识符                             |
| `CharacterName`                   | `string`                 | 读取  | 角色的显示名称                                  |
| `OwnerId`                         | `string`                 | 读取  | 拥有者账户标识符                                 |
| `SessionState`                    | `SessionState`           | 读取  | 此单个角色的当前会话状态                             |
| `IsCharacterReady`                | `bool`                   | 读取  | 当角色已完成就绪握手时为 True                        |
| `IsSessionConnected`              | `bool`                   | 读取  | 当此角色的会话处于 `已连接` state                    |
| `IsInConversation`                | `bool`                   | 读取  | 当此角色是活动对话目标时为 True                       |
| `IsSpeaking`                      | `bool`                   | 读取  | 当角色正在主动输出音频时为 True                       |
| `IsRemoteAudioEnabled`            | `bool`                   | 读取  | 当此角色的远程音频输出已启用时为 True                    |
| `CurrentEmotion`                  | `string`                 | 读取  | 从 Convai 收到的最新情绪标签                       |
| `CurrentEmotionIntensity`         | `int`                    | 读取  | 最新情绪强度（1–3）                              |
| `ConfigurationSource`             | `ConvaiConfigSourceMode` | 读取  | 配置来自 Inspector 字段还是配置文件资源                |
| `CharacterConfigAsset`            | `ConvaiCharacterProfile` | 读取  | 当……时的配置文件资源 `ConfigurationSource` 为基于资源时 |
| `NameTagColor`                    | `Color`                  | 读取  | UI 中用于此角色名称标签的颜色                         |
| `EnableRemoteAudioOnStart`        | `bool`                   | 读取  | 远程音频输出是否在启动时默认启用                         |
| `EnableSessionResume`             | `bool`                   | 读取  | 连接恢复后会话是否尝试继续                            |
| `CharacterReadyTimeoutSeconds`    | `float`                  | 读/写 | 等待角色就绪握手的超时时间（秒）                         |
| `InitialDynamicInfoText`          | `string`                 | 读取  | 会话开始时发送的动态上下文文本                          |
| `InitialDynamicInfoKeepInContext` | `bool`                   | 读取  | 初始动态上下文是否在多个轮次中持续保留                      |
| `动作配置`                            | `ConvaiActionConfig`     | 读取  | 此角色的动作配置                                 |
| `DynamicContext`                  | `IConvaiDynamicContext`  | 读取  | 动态上下文命令接口                                |
| `NarrativeDesign`                 | `IConvaiNarrativeDesign` | 读取  | 叙事设计接口                                   |
| `IsInjected`                      | `bool`                   | 读取  | 当依赖项已由 SDK 注入时为 True                     |

#### `ConvaiConfigSourceMode` 枚举

| 值    | 描述                                |
| ---- | --------------------------------- |
| `内联` | 直接在 Inspector 中设置到组件上的配置          |
| `资源` | 配置加载自 `ConvaiCharacterProfile` 资源 |

#### 会话控制

| 方法                                                                                         | 返回                       | 描述                                                   |
| ------------------------------------------------------------------------------------------ | ------------------------ | ---------------------------------------------------- |
| `StartConversationAsync(CancellationToken ct = default)`                                   | `IConvaiOperation<Unit>` | 为此角色启动一个对话会话                                         |
| `StopConversationAsync(CancellationToken ct = default)`                                    | `IConvaiOperation<Unit>` | 停止此角色的对话会话                                           |
| `WaitForCharacterReadyAsync(float? timeoutSeconds = null, CancellationToken ct = default)` | `IConvaiOperation<Unit>` | 等待角色完成就绪握手。在……之后使用 `StartConversationAsync` 再发送输入之前。 |
| `ResetAndRetryAsync(CancellationToken ct = default)`                                       | `IConvaiOperation<Unit>` | 重置角色的会话状态并重试初始化。在出错后使用。                              |
| `Reset()`                                                                                  | `bool`                   | 同步重置本地会话状态。返回 `true` 如果重置已应用。                        |

```csharp
// 连接并等待角色就绪后再发送输入
var startOp = character.StartConversationAsync(destroyCancellationToken);
await startOp;
if (startOp.IsSuccessful)
{
    await character.WaitForCharacterReadyAsync(timeoutSeconds: 10f, destroyCancellationToken);
    Debug.Log("角色已可接收输入。");
}
```

#### 语音控制

| 方法                    | 返回                       | 描述                     |
| --------------------- | ------------------------ | ---------------------- |
| `ToggleSpeech()`      | `void`                   | 切换角色的对话会话。断开时启动；连接时停止。 |
| `ToggleSpeechAsync()` | `IConvaiOperation<Unit>` | 的异步版本 `ToggleSpeech`.  |

#### 远程音频控制

| 方法                                    | 返回     | 描述                                    |
| ------------------------------------- | ------ | ------------------------------------- |
| `SetRemoteAudioEnabled(bool enabled)` | `bool` | 设置此角色的音频输出是否在本地播放。如果更改已应用，返回 `true` 。 |
| `EnableRemoteAudio()`                 | `bool` | 启用此角色的音频输出。返回 `true` 如果已应用。           |
| `DisableRemoteAudio()`                | `bool` | 禁用此角色的音频输出。返回 `true` 如果已应用。           |
| `ToggleRemoteAudio()`                 | `void` | 切换此角色的音频输出状态。                         |

{% hint style="info" %}
按角色进行音频控制，可以在多角色场景中单独静音某个角色——例如，在主讲角色发言时静音辅助讲师。若要静音麦克风（你的输入），请使用 `ConvaiManager.ActiveManager.Audio`.
{% endhint %}

#### 动态上下文和叙事

| 方法                                                              | 返回     | 描述                                               |
| --------------------------------------------------------------- | ------ | ------------------------------------------------ |
| `SendDynamicInfo(string contextText)`                           | `void` | 向 Convai 发送此角色的动态上下文更新。无需重新连接即可更新角色会话内上下文。       |
| `SendTrigger(string triggerName, string triggerMessage = null)` | `void` | 按名称发送叙事设计触发器。 `triggerMessage` 如果提供，则覆盖触发器配置的消息。 |
| `UpdateTemplateKeys(Dictionary<string, string> templateKeys)`   | `void` | 更新叙事设计模板键值，以便进行动态叙事变量替换。                         |

#### 注意力与动作

| 方法                                                                                                                               | 返回                         | 描述                          |
| -------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | --------------------------- |
| `DynamicContext.SetCurrentAttentionObject(object currentAttentionObject, ConvaiRespondMode reaction = ConvaiRespondMode.Silent)` | `void`                     | 按名称或动作对象资源设置角色当前正在关注的场景内对象。 |
| `DynamicContext.ClearCurrentAttentionObject(ConvaiRespondMode reaction = ConvaiRespondMode.Silent)`                              | `void`                     | 清除当前场景内的关注对象。               |
| `GetActionConfigSource()`                                                                                                        | `ConvaiActionConfigSource` | 返回此角色的动作配置源组件。              |

#### `ConvaiCharacter` 事件

在以下位置订阅 `OnEnable`，在……中取消订阅 `OnDisable`.

| 事件                            | 签名                                           | 触发时                              |
| ----------------------------- | -------------------------------------------- | -------------------------------- |
| `OnTranscriptReceived`        | `Action<string, bool>`                       | 转录到达。参数：text、isFinal。            |
| `OnSpeechStarted`             | `操作`                                         | 角色开始输出音频                         |
| `OnSpeechStopped`             | `操作`                                         | 角色停止输出音频                         |
| `OnTurnCompleted`             | `Action<bool>`                               | 角色的对话轮次结束。参数：wasInterrupted。     |
| `OnCharacterReady`            | `操作`                                         | 角色完成就绪握手                         |
| `OnSessionStateChanged`       | `Action<SessionState>`                       | 此角色的单独会话状态发生变化                   |
| `OnEmotionChanged`            | `Action<string, int>`                        | 情绪变化。参数：emotion label、原始强度（1–3）。 |
| `OnActionsReceived`           | `Action<IReadOnlyList<ConvaiActionCommand>>` | Convai 为此角色发送场景内动作命令             |
| `OnRemoteAudioEnabledChanged` | `Action<bool>`                               | 此角色的远程音频输出已启用或禁用                 |

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

public class CharacterSessionMonitor : MonoBehaviour
{
    [SerializeField] private ConvaiCharacter _character;

    private void OnEnable()
    {
        _character.OnSessionStateChanged      += OnStateChanged;
        _character.OnRemoteAudioEnabledChanged += OnAudioChanged;
        _character.OnCharacterReady            += OnReady;
    }

    private void OnDisable()
    {
        _character.OnSessionStateChanged      -= OnStateChanged;
        _character.OnRemoteAudioEnabledChanged -= OnAudioChanged;
        _character.OnCharacterReady            -= OnReady;
    }

    private void OnStateChanged(SessionState state) =>
        Debug.Log($"[{_character.CharacterName}] 会话状态：{state}");

    private void OnAudioChanged(bool enabled) =>
        Debug.Log($"[{_character.CharacterName}] 音频输出：{(enabled ? "开启" : "关闭")}");

    private void OnReady() =>
        Debug.Log($"[{_character.CharacterName}] 已就绪。");
}
```

***

### `ConvaiPlayer`

`ConvaiPlayer` 表示会话中的本地人类参与者。它拥有玩家的显示名称和身份，并提供文本消息发送功能。

#### 属性

| 属性             | 类型       | 访问 | 描述               |
| -------------- | -------- | -- | ---------------- |
| `PlayerName`   | `string` | 读取 | 玩家的显示名称          |
| `PlayerId`     | `string` | 读取 | 玩家身份标识符          |
| `NameTagColor` | `Color`  | 读取 | UI 中用于此玩家名称标签的颜色 |

#### 方法

| 方法                                                     | 返回     | 描述                                                   |
| ------------------------------------------------------ | ------ | ---------------------------------------------------- |
| `SendTextMessage(string message)`                      | `void` | 作为此玩家向 Convai 发送文本消息，绕过麦克风输入。适用于文本输入模式或程序化玩家对话。      |
| `Configure(string playerName, string playerId = null)` | `void` | 设置玩家的显示名称和可选身份。请在……之前调用 `ConnectAsync` 以确保在会话中使用该身份。 |
| `SetRuntimeDisplayName(string displayName)`            | `void` | 在运行时更新玩家的显示名称，而不改变身份。会反映在转录参与者名称中。                   |

#### `ConvaiPlayer` 事件

| 事件                  | 签名               | 触发时                            |
| ------------------- | ---------------- | ------------------------------ |
| `OnTextMessageSent` | `Action<string>` | 文本消息通过以下方式发送 `SendTextMessage` |

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

public class TextInputController : MonoBehaviour
{
    [SerializeField] private TMP_InputField _inputField;

    public void OnSubmit()
    {
        var text = _inputField.text.Trim();
        if (string.IsNullOrEmpty(text)) return;

        ConvaiManager.ActiveManager?.Player?.SendTextMessage(text);
        _inputField.text = string.Empty;
    }
}
```

***

### 使用示例

#### 示例 1 — 连接角色并在就绪状态后继续

医学培训模拟会确保 AI 医生角色在评估开始前完全就绪，从而防止学习者与尚未初始化的角色对话。

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

public class AssessmentStarter : MonoBehaviour
{
    [SerializeField] private ConvaiCharacter _physician;
    [SerializeField] private GameObject      _startPanel;

    private async void Start()
    {
        _startPanel.SetActive(false);

        var startOp = _physician.StartConversationAsync(destroyCancellationToken);
        await startOp;
        if (!startOp.IsSuccessful)
        {
            Debug.LogError($"角色连接失败：{startOp.Error.Message}");
            return;
        }

        var readyOp = _physician.WaitForCharacterReadyAsync(
            timeoutSeconds: 15f, destroyCancellationToken);
        await readyOp;

        if (readyOp.IsSuccessful)
            _startPanel.SetActive(true);
        else
            Debug.LogWarning("角色就绪超时 — 请检查你的 API 密钥和网络。");
    }
}
```

#### 示例 2 — 在多 NPC 场景中按角色切换音频

企业入职培训模拟中有三位 AI 顾问。一个 UI 面板允许学习者静音任意单个顾问，而不会影响其他顾问。

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

public class AdvisorMuteButton : MonoBehaviour
{
    [SerializeField] private ConvaiCharacter _advisor;
    [SerializeField] private Button         _muteButton;
    [SerializeField] private Sprite         _mutedIcon;
    [SerializeField] private Sprite         _unmutedIcon;

    private Image _buttonImage;

    private void Awake() => _buttonImage = _muteButton.GetComponent<Image>();

    private void OnEnable()
    {
        _muteButton.onClick.AddListener(OnToggleMute);
        _advisor.OnRemoteAudioEnabledChanged += RefreshIcon;
        RefreshIcon(_advisor.IsRemoteAudioEnabled);
    }

    private void OnDisable()
    {
        _muteButton.onClick.RemoveListener(OnToggleMute);
        _advisor.OnRemoteAudioEnabledChanged -= RefreshIcon;
    }

    private void OnToggleMute() => _advisor.ToggleRemoteAudio();

    private void RefreshIcon(bool enabled) =>
        _buttonImage.sprite = enabled ? _unmutedIcon : _mutedIcon;
}
```

#### 示例 3 — 面向可访问性的文本输入模式

工业安全模拟为无法或受限访问麦克风的环境提供了文本输入备用方案。

```csharp
using Convai.Runtime.Facades;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class AccessibilityTextInput : MonoBehaviour
{
    [SerializeField] private TMP_InputField _inputField;
    [SerializeField] private Button        _submitButton;

    private void OnEnable()  => _submitButton.onClick.AddListener(Submit);
    private void OnDisable() => _submitButton.onClick.RemoveListener(Submit);

    private void Submit()
    {
        var text = _inputField.text.Trim();
        if (string.IsNullOrEmpty(text)) return;

        var player = ConvaiManager.ActiveManager?.Player;
        if (player == null) return;

        player.SendTextMessage(text);
        _inputField.text = string.Empty;
        _inputField.ActivateInputField(); // 保持焦点以便快速输入
    }
}
```

***

### 故障排除

| 症状                                   | 可能原因                                         | 修复                                                        |
| ------------------------------------ | -------------------------------------------- | --------------------------------------------------------- |
| `WaitForCharacterReadyAsync` 超时      | 角色从未收到来自 Convai 的就绪确认                        | 验证 API 密钥，检查网络；在……之后调用 `StartConversationAsync` 成功后，而不是之前 |
| `SendDynamicInfo` 没有可见效果             | 在角色会话连接之前调用                                  | 在……之后调用 `WaitForCharacterReadyAsync` 成功解析                 |
| `ToggleRemoteAudio()` 没有效果           | `EnableRemoteAudioOnStart` 是 `false` 且从未启用音频 | 调用 `EnableRemoteAudio()` 先启用音频，然后再切换                      |
| `SendTextMessage` 已发送，但角色没有回应        | 会话不在 `已连接` state                             | 检查 `character.IsSessionConnected` 发送之前                    |
| `OnActionsReceived` 已触发，但没有执行任何场景内动作 | `ConvaiActionDispatcher` 不在场景中，或动作名称不匹配      | 验证分发器是否存在；动作名称不区分大小写，但必须与配置的名称一致                          |

***

### 下一步

有关房间级别的音频和麦克风控制，请参见 [音频 API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/audio-api.md)。有关会话连接控制，请参见 [ConvaiManager API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/convaimanager-api.md)。有关通过 relay 或 C# hub 订阅角色事件，请参见 [角色事件](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/scripting-reference/character-events.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 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/scripting-reference/character-and-player-api.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.
