> 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-unreal-engine-plugin/features/character-actions/how-character-actions-work.md).

# 角色动作的工作方式

角色动作将 Convai 所说内容与角色在关卡中实际执行的行为连接起来。当玩家说话时，Convai 可以同时返回一段口头回复和一串命名动作——前往某个地点、跟随玩家、与对象交互。插件会将这些动作分发到 NPC Actor 上对应的 Blueprint 处理函数事件，并按顺序一次执行一个。

### 所需设置

| 组件 / 资源                       | 所需用途              | 注意                                                   |
| ----------------------------- | ----------------- | ---------------------------------------------------- |
| `Convai 聊天机器人` 组件             | 所有动作              | 携带 `环境` 属性（动作模板、对象、角色）以及 `ActionsQueue`.             |
| `Convai Player` 组件            | 所有动作              | 玩家 Pawn 上用于语音输入所必需。                                  |
| Blueprint 处理函数                | 每个应执行的动作          | 每个动作名对应一个函数，接收 `FConvaiResultAction`.                |
| NPC Actor 上的 AI Controller    | 移动动作（`移动到`, `跟随`) | 所需用途 `AI Move To` 才能工作。使用 Unreal 内置的 `AIController`. |
| `Nav Mesh Bounds Volume` （内置） | 移动动作              | 必须覆盖 NPC 生成点和所有导航目标。关卡变更后请重新构建。                      |

对于非移动动作（自定义行为、动画、状态变化），只需要聊天机器人组件和 Blueprint 处理函数。

### 关键概念

六个概念支撑着系统的工作方式。下面每一节都会详细介绍其中一个，但这里先给出一个快速概览：

| 概念         | 含义                                                                  |
| ---------- | ------------------------------------------------------------------- |
| **动作契约**   | 会话开始前发送给 Convai 的动作、对象和角色列表——定义了角色被允许执行和引用的内容。                      |
| **动作流水线**  | 两条并行通道：一条播放语音音频，另一条按顺序存储并执行一串动作。                                    |
| **队列与分发**  | 插件会维护一个待处理动作队列。每次处理器报告完成后，队列前进一个位置，并运行下一个处理器。                       |
| **完成模型**   | 每个处理器在完成时都必须调用 `HandleActionCompletion` 。如果没有这次调用，队列就会停滞，后续动作也不会运行。 |
| **等待语音门控** | 一个可选的按动作设置的标志，它会在角色开始说话或说完之前延迟触发该动作，使移动与语音保持同步。                     |
| **运行时变更**  | 对象和角色可以在会话进行时添加或移除；本地环境会立即更新。                                       |

### 动作契约

会话开始前，聊天机器人组件会读取 `环境` 属性——其中包含动作模板、已注册对象和角色列表——并将这些信息发送给 Convai。Convai 会据此了解角色可以执行哪些动作，以及在响应玩家语音时可引用哪些对象。

该契约包含三部分：

* **动作** ——一个有序的 `FConvaiAction` 模板，每个模板都有名称、可选描述以及可选的带类型参数。该列表定义在 `环境` 的属性中 `UConvaiChatbotComponent`，位于 `动作` 字段。
* **对象** ——一个 `FConvaiObjectEntry` 数组，其中的值用于描述可交互的场景对象。每个条目都有一个 `名称`，一个可选的 `描述`，以及导航目标字段。
* **角色** ——一个 `FConvaiObjectEntry` 用于描述场景中其他角色的值。

该 **启用动作** 切换开启 `Convai 聊天机器人` 组件的 `环境` 属性充当总开关。它默认设为 `true` ，适用于每个新组件，因此该功能开箱即用即启用。禁用后，契约不会在会话开始时发送，角色会表现为纯对话型 NPC。

{% hint style="info" %}
会话开始时，动作集就已固定。通过 `AddAction` / `RemoveAction` 在运行时添加或移除动作只会影响下一次会话——当前进行中的会话仍保留其连接时的那一套动作。
{% endhint %}

### 动作流水线

当玩家与 Convai 角色对话时，插件会通过两条并行通道处理响应：

1. **语音通道** ——音频流会传送到角色的音频组件进行播放。聊天机器人会触发 `收到动作` 和 `OnStartedTalking` / `OnFinishedTalking` 事件，随着语音进展而触发。
2. **动作通道** ——Convai 会根据 `action_config` 契约解析响应，并返回一串 `FConvaiResultAction` 结构体。插件将该序列存储在 `ActionsQueue` on `UConvaiChatbotComponent`.

两条通道彼此独立。语音播放的同时，动作队列也在执行。

### 队列与分发

插件维护一个 `FConvaiResultAction` 条目队列，存放于 `ActionsQueue`中。当新的动作序列到达时，插件会：

1. 如果队列中已经有一个正在进行的动作，就保留第一个动作，并用传入的序列替换其余排队动作。如果队列为空，则原样存储传入的序列。
2. 调用 `StartFirstAction`，它会从队列中读取第一项并调用 `TriggerNamedBlueprintAction`.
3. `TriggerNamedBlueprintAction` 会查找名称与结果的 `Action` 字段匹配的 Blueprint 函数或事件。它会先检查所属 Actor，再检查聊天机器人组件。该处理函数可以接受一个 `FConvaiResultAction` 参数，或者不接受参数。

分发器基于名称。Unreal 解析处理器名称时不区分大小写，但空格和标点仍必须匹配。如果在任一目标上都找不到匹配函数，插件会记录警告，处理器不会被调用，队列会停滞，直到 `HandleActionCompletion` 或 `AbortActionSequence` 被调用。

### 取消动作计划

当某个动作仍在运行时，角色可以改变路线——玩家重新引导它，或者新的情况让当前计划变得毫无意义。 `CancelCurrentActionPlan` on `UConvaiChatbotComponent` （蓝图显示名称 **取消当前动作计划**）会以协作方式取消，而不是直接把队列从正在运行的处理器脚下抽走：排队中的动作会立即丢弃，但当前活动处理器会获得一个可选的 Blueprint 事件，名称正好为 `Cancel <动作名>`，并携带原始的 `FConvaiResultAction`，以便在替代计划开始前干净地停止其计时器、委托或延迟任务。重复调用只会请求一次取消，并等待一次终态确认。

实现了可选取消事件的处理器必须调用 `HandleActionCancellation` ，一旦它完全静止下来——也就是在其计时器、委托、任务和回调都停止之后。该调用不报告成功或失败，并会释放所持有的替代计划，使队列能够继续前进。未实现取消事件的处理器则由其自行完成；无论哪种情况，自定义取消处理器都必须且只能调用一个终态 API—— `HandleActionCancellation` 或者其现有的完成路径——绝不能两者都调用。

启用 `bEnableCancelActionPlanAction` （蓝图显示名称 **启用取消动作计划**，类别 `Convai|Actions|Experimental`）在聊天机器人组件上会添加一个保留的 `取消动作计划` 控制动作到发送给 Convai 的契约中，因此当玩家重新引导或放弃角色正在执行的事情时，角色本身可以决定是否调用取消。参见 [配置动作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/character-actions/configuring-actions.md#experimental-built-in-actions) 了解该切换项，以及 [动作蓝图参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/character-actions/actions-blueprint-reference.md) 查看完整的函数和事件列表。

### 等待语音门控

`FConvaiAction` 都有一个 `bWaitForBotSpeech` 标志。当它设置在某个动作模板上，且该动作作为新接收序列中的第一个动作到达时（即序列到达时队列为空），插件会延迟启动该动作，直到 Convai 开始说话（`OnStartedTalking`）或说完（`OnFinishedTalking`），以先触发者为准。每个角色的超时（`ActionWaitForBotSpeechTimeoutSec`，默认 `2.0` 秒，不对 Blueprint 暴露）会在两种语音事件都未及时到达时仍然触发该动作。

一个可选的 `DelayAfterBotSpeechSec` 字段会在语音条件满足后再额外增加延迟。

### 完成模型

处理器负责报告结果。处理器完成工作后，必须调用 `HandleActionCompletion` 位于 `UConvaiChatbotComponent`:

* `IsSuccessful = true` ——插件会将当前动作出队并开始下一个。
* `IsSuccessful = false` ——插件会清空剩余队列。角色不会尝试下一个动作。

当 `bAutoReport` 为 `true` （默认），插件还会向 Convai 发送一条描述结果的上下文事件。Convai 会在生成角色下一次口头回复时使用这些信息。

如果处理器遇到无法恢复的错误，并希望 Convai 生成一个全新的动作计划，它会调用 `AbortActionSequence` ，并可选地传入一段关于出错原因的文本说明。

下图展示了一个从开始到完成的单动作交互。当序列包含多个动作时，每次 `HandleActionCompletion(true)` 调用都会让队列前进一步。

```mermaid
sequenceDiagram
    participant Player
    participant Convai
    participant Plugin
    participant Handler

    Player->>Convai: 语音输入
    Convai-->>Plugin: 语音音频 + 动作序列
    Plugin->>Plugin: 更新 ActionsQueue
    Plugin->>Handler: TriggerNamedBlueprintAction(Action, ResultAction)
    Handler->>Handler: 执行行为
    Handler->>Plugin: HandleActionCompletion(IsSuccessful)
    Plugin->>Plugin: 出队并开始下一个动作
    Plugin->>Convai: 上下文事件（结果）
```

### 运行时环境变更

可在运行时使用 `AddObject`, `RemoveObject`, `AddCharacter`，以及 `RemoveCharacter` 上的一组方法 `UConvaiChatbotComponent`向本地环境添加或移除对象和角色。本地 `EnvironmentData` 镜像会立即反映这些变化，并在插件解析后续动作结果时使用。

运行时变更不会改变动作集本身，动作集在下次重新连接之前保持固定。对于实时会话，场景上下文更新会通过 `update-scene-metadata` 在变更的条目尚未包含在连接时的场景元数据快照中时发送。

### 下一步

{% content-ref url="/pages/9d759a9e65c274645e91b88390d8bb2c4762bd80" %}
[配置动作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/character-actions/configuring-actions.md)
{% endcontent-ref %}

{% content-ref url="/pages/d1aaea82f339a27b3ce67918aa343caebba0762c" %}
[内置动作处理程序](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/character-actions/built-in-action-handlers.md)
{% endcontent-ref %}

{% content-ref url="/pages/4034933484ffa13478584311631f11ea8d503bb4" %}
[构建自定义动作处理程序](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/character-actions/building-custom-action-handlers.md)
{% endcontent-ref %}

{% content-ref url="/pages/8e18d509947b40274dca96b384f432486348198f" %}
[动作 Blueprint 参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/character-actions/actions-blueprint-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 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-unreal-engine-plugin/features/character-actions/how-character-actions-work.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.
