> 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/character-actions/action-executors.md).

# 动作执行器

执行器是在调度器运行某个动作步骤时执行场景内行为的组件——例如行走、指向、改变情绪或播放声音的 NPC。Convai SDK 随附 21 个执行器组件，分为六个套件。每个都带有一个 `ConvaiActionArchetype` 属性，因此从 Actions Editor 的 **+ 添加动作 ▾** 目录中添加一个时，会自动预填其动作名称、描述、目标要求以及任何参数——无需手动编写即可获得一个可工作的动作。

这 21 个都继承自 `ConvaiActionExecutorBase` (`Convai.Runtime.Actions`），大多通过 `ConvaiTargetedActionExecutor` 或通用的 `ConvaiCharacterActionExecutor<TPeer>`。基于 `ConvaiCharacterActionExecutor<TPeer>` 的执行器，会在下方每个执行器所列字段之外，再额外暴露一个 Inspector 字段—— **角色组件**，即对端组件的引用（例如 `ConvaiGazeController`）它所通过的组件。留空时，执行器会自动查找该对端，先搜索此 `GameObject`的父级，再搜索其子级；只有当角色携带该对端类型的多个实例时，才显式指定它。

### Flow 与 Utility 套件（`Convai.Runtime`)

无模块套件，位于 `SDK/Runtime/Actions/Executors/` ——这里的每个行为都适用于任意项目中的任意角色，不需要 Convai 模块。

#### 触发 Unity 事件

运行你接入到其事件中的任何内容，然后始终成功。对于场景中本来就能通过按钮完成的任何事情，这都是一个无代码的快捷出口——打开门、开始时间轴、加一点分。

| 属性         | 值                                       |
| ---------- | --------------------------------------- |
| **类**      | `ConvaiUnityEventActionExecutor`        |
| **菜单路径**   | `添加组件 → Convai → Actions → 触发 Unity 事件` |
| **原型动作名称** | `触发 Unity 事件`                           |
| **目标要求**   | 无                                       |
| **所需对端**   | 无                                       |

**检查器字段：**

| 字段           | 类型           | 默认值 | 描述                                   |
| ------------ | ------------ | --- | ------------------------------------ |
| `_onExecute` | `UnityEvent` | 空   | 每次动作运行时都会调用。可在 Inspector 中接入任意数量的回调。 |

绝不会失败——即使没有接线的事件也仍会报告成功；Actions Editor 会在编写时标记未接线的事件。若动作需要读取参数、耗时、可被取消，或报告其无法运行的原因，请编写自定义执行器。

#### 等待

暂停几秒，除此之外什么也不做。单独使用很少有用；在 **按顺序运行** 它才是让一段表演拥有节奏的关键——先指向门，停顿一下，然后走过去。

| 属性         | 值                              |
| ---------- | ------------------------------ |
| **类**      | `ConvaiWaitActionExecutor`     |
| **菜单路径**   | `添加组件 → Convai → Actions → 等待` |
| **原型动作名称** | `等待`                           |
| **目标要求**   | 无                              |
| **所需对端**   | 无                              |

**检查器字段：**

| 字段            | 类型      | 默认值  | 描述                                                    |
| ------------- | ------- | ---- | ----------------------------------------------------- |
| `_seconds`    | `float` | `1`  | 要等待多久。角色可以通过 `seconds` 参数请求不同的时长。                     |
| `_maxSeconds` | `float` | `30` | 允许的最长等待时间。会同时限制 Inspector 值和角色请求的任何值，因此一个错误数字不会让场景卡住。 |

该等待是逐帧且可取消的——它从不使用 `Task.Delay` ——因此它按正常游戏节奏运行，遵守暂停和时间缩放，并在动作被取消时正确退出。

#### 按顺序运行

将多个 Action Behavior 作为单个动作依次运行——“向来访者打招呼”可以表示看向对方、点头并问好，全程无需代码编写。每一步都会接收相同的目标和参数。

| 属性         | 值                                 |
| ---------- | --------------------------------- |
| **类**      | `ConvaiSequenceActionExecutor`    |
| **菜单路径**   | `添加组件 → Convai → Actions → 按顺序运行` |
| **原型动作名称** | `按顺序运行`                           |
| **目标要求**   | 无（传递给每一步）                         |
| **所需对端**   | 无                                 |

**检查器字段：**

| 字段       | 类型                    | 默认值 | 描述                                                             |
| -------- | --------------------- | --- | -------------------------------------------------------------- |
| `_steps` | `List<MonoBehaviour>` | 空   | 要运行的 Action Behavior，自上而下排列。每个条目都必须实现 `IConvaiActionExecutor`. |

在第一个未成功的步骤处停止，并返回该步骤自身的结果，同时以前缀标明其位置——失败会指出是哪一步失败以及原因。空条目、不是 Action Behavior 的条目，或引用此同一组件的条目都会立即失败，返回 `ConvaiActionFailureReason.InvalidState`.

#### 显示或隐藏对象

将目标对象打开或关闭——从“把地图给他们看”到让某个可见变化发生的最短路径，而且对象本身无需额外组件。

| 属性         | 值                                   |
| ---------- | ----------------------------------- |
| **类**      | `ConvaiSetActiveActionExecutor`     |
| **菜单路径**   | `添加组件 → Convai → Actions → 显示或隐藏对象` |
| **原型动作名称** | `显示或隐藏对象`                           |
| **目标要求**   | 对象                                  |
| **所需对端**   | 无                                   |

**检查器字段：**

| 字段      | 类型                                          | 默认值  | 描述                               |
| ------- | ------------------------------------------- | ---- | -------------------------------- |
| `_mode` | `ConvaiShowHideMode` (`显示`, `隐藏`, `Toggle`) | `显示` | 对对象执行什么操作。角色可以通过 `模式` 参数请求不同的时长。 |

请求对象已经处于的状态会成功并明确说明（“Already showing.”），而不是失败——满足的请求是被完成，而不是失败。未解析到目标时返回 `Unhandled`.

#### 播放 Animator 状态

**适用于使用自身 Animator Controller 进行动画的角色，而不是 Body Animation 模块。** 将动作名称映射为一个 Trigger 参数并设置它，并且可选择等待由此产生的状态结束。

| 属性         | 值                                                                  |
| ---------- | ------------------------------------------------------------------ |
| **类**      | `ConvaiAnimatorStateActionExecutor`                                |
| **菜单路径**   | `添加组件 → Convai → Actions → 播放 Animator 状态（自身 Animator Controller）` |
| **原型动作名称** | `播放 Animator 状态`                                                   |
| **目标要求**   | 无                                                                  |
| **所需对端**   | `Animator`                                                         |

**检查器字段：**

| 字段          | 类型                                  | 默认值 | 描述                          |
| ----------- | ----------------------------------- | --- | --------------------------- |
| `_bindings` | `List<ConvaiAnimatorActionBinding>` | 空   | 角色可通过 Animator 执行的每个动作对应一行。 |

**`ConvaiAnimatorActionBinding` 行字段：**

| 字段                   | 类型       | 默认值    | 描述                                                          |
| -------------------- | -------- | ------ | ----------------------------------------------------------- |
| `ActionName`         | `string` | —      | 要响应的动作名称，大小写不敏感匹配。                                          |
| `TriggerName`        | `string` | —      | 该动作运行时要设置的 Animator Trigger 参数。                             |
| `WaitForStateTag`    | `string` | 空      | 可选。用相同词语为 Animator 状态加上标签，以便在动作结束前等待它。留空则在 Trigger 设定后立即结束。 |
| `NormalizedExitTime` | `float`  | `0.95` | 标签状态推进到多大程度才算完成（`0`–`1`）。仅在 `WaitForStateTag` 已设置时使用。       |

没有匹配行的动作名称会被拒绝为 `Unhandled` 而不是失败，因此角色上的另一个 Action Behavior 仍有机会响应它。如果角色有一个，拒绝消息会写明 `ConvaiBodyAnimationController`播放手势 **而改为使用——这两个行为驱动同一个 Animator，如果一起使用就会互相冲突。** 播放声音

#### 通过普通的

。无论有无目标都适用——这个选择在编写动作时确定：没有目标且已分配 `AudioSource`的 `AudioSource` 会直接播放声音；有目标但没有 `AudioSource` 分配时，则从角色被要求作用的对象上播放。

| 属性         | 值                                |
| ---------- | -------------------------------- |
| **类**      | `ConvaiPlaySoundActionExecutor`  |
| **菜单路径**   | `添加组件 → Convai → Actions → 播放声音` |
| **原型动作名称** | `通过普通的`                          |
| **目标要求**   | 任一                               |
| **所需对端**   | 无                                |

**检查器字段：**

| 字段                      | 类型            | 默认值     | 描述                                   |
| ----------------------- | ------------- | ------- | ------------------------------------ |
| `_audioSource`          | `AudioSource` | `null`  | 通过哪个源播放。留空则使用目标对象上的一个源。              |
| `_clip`                 | `AudioClip`   | `null`  | 要播放的声音。留空则播放 `AudioSource` 已拥有的任意剪辑。 |
| `_volume`               | `float`       | `1`     | 播放音量， `0`–`1`。角色可以通过 `音量` 参数请求不同的时长。 |
| `_waitForSoundToFinish` | `bool`        | `false` | 保持动作开启直到剪辑结束。                        |

绝不会通过角色自己的语音 `AudioSource` ——借用它会在角色说到一半时把它打断。若既没有分配的源，也没有目标上的源，动作会被拒绝并提示应分配什么。没有剪辑时解析为 `Failed`.

### 注意力套件（`Convai.Modules.Gaze`)

`SDK/Modules/Gaze/Executors/` ——这里的每个行为都需要一个 `ConvaiGazeController` 对端。

#### 注视目标

将角色的注意力转向目标——眼睛先看，头部跟随，若目标位于头部无法转到的位置，身体也会转向。一旦注视明显到位就结束，而不是等保持时间结束，因此后续步骤不会排在保持时间之后。

| 属性         | 值                                |
| ---------- | -------------------------------- |
| **类**      | `ConvaiLookAtActionExecutor`     |
| **菜单路径**   | `添加组件 → Convai → Actions → 注视目标` |
| **原型动作名称** | `注视`                             |
| **目标要求**   | 任一                               |
| **所需对端**   | `ConvaiGazeController`           |
| **超时**     | 10s（原型默认值）                       |

**检查器字段：**

| 字段             | 类型                                 | 默认值   | 描述                                                         |
| -------------- | ---------------------------------- | ----- | ---------------------------------------------------------- |
| `_mode`        | `ConvaiGazeLookMode` (`瞥一眼`, `持续`) | `持续`  | 瞥一眼是快速看一下就移开；持续则是角色保持的专注注视，必要时会转动身体。角色可以通过 `模式` 参数请求不同的时长。 |
| `_holdSeconds` | `float`                            | `2.5` | 注视到位后要持续看多久。 `0` 会一直看着，直到其他事物吸引角色的注意力。                     |
| `_engagement`  | `float`                            | `1`   | 注视得有多专注， `0`–`1`.                                          |

为保持与正在交谈对象的眼神接触而拒绝的瞥视会报告 `Unhandled` （眼神接触锁定按预期工作），而不是失败。

#### 注视玩家

与玩家保持眼神接触，直到被告知停止——这是一个有范围、可取消的请求，与角色自身的对话眼神接触设置不同，本动作不会更改该设置。

| 属性         | 值                                 |
| ---------- | --------------------------------- |
| **类**      | `ConvaiWatchPlayerActionExecutor` |
| **菜单路径**   | `添加组件 → Convai → Actions → 注视玩家`  |
| **原型动作名称** | `注视玩家`                            |
| **目标要求**   | 无（玩家是隐含的）                         |
| **所需对端**   | `ConvaiGazeController`            |

**检查器字段：**

| 字段            | 类型                                     | 默认值  | 描述                                                |
| ------------- | -------------------------------------- | ---- | ------------------------------------------------- |
| `_mode`       | `ConvaiWatchPlayerMode` (`注视`, `停止注视`) | `注视` | 本次调用是开始注视还是停止注视。角色可以通过 `模式` 参数（`watch` 或 `stop`). |
| `_engagement` | `float`                                | `1`  | 注视得有多专注， `0`–`1`.                                 |

场景中找不到玩家会失败并返回 `ConvaiActionFailureReason.TargetMissing`。如果组件在注视过程中被禁用，注视会自动释放。

#### 扫描环境

检查周围环境中的多个不同点，优先选择搜索半径内的场景对象，否则退回到均匀分布的世界点。

| 属性         | 值                                     |
| ---------- | ------------------------------------- |
| **类**      | `ConvaiScanEnvironmentActionExecutor` |
| **菜单路径**   | `添加组件 → Convai → Actions → 扫描环境`      |
| **原型动作名称** | `扫描环境`                                |
| **目标要求**   | 无                                     |
| **所需对端**   | `ConvaiGazeController`                |
| **超时**     | 15s（原型默认值）                            |

**检查器字段：**

| 字段                  | 类型          | 默认值     | 描述                                 |
| ------------------- | ----------- | ------- | ---------------------------------- |
| `_durationSeconds`  | `float`     | `3.5`   | 总扫描时长。角色可以通过 `duration` 参数请求不同的时长。 |
| `_stopCount`        | `int`       | `4`     | 注视会停留的不同点数量， `2`–`8`.              |
| `_arcDegrees`       | `float`     | `150`   | 覆盖的水平范围，以角色前方为中心， `20`–`320`.      |
| `_allowBodyTurn`    | `bool`      | `false` | 较宽的扫描点是否允许身体也随头部和眼睛一起转动。           |
| `_searchRadius`     | `float`     | `7`     | 用于查找值得检查的场景碰撞体的半径。 `0` 仅使用生成的点。    |
| `_targetLayers`     | `LayerMask` | 全部      | 包含可被选作扫描点的对象的图层。                   |
| `_fallbackDistance` | `float`     | `4`     | 当没有场景对象适合该弧度时，生成扫描点的距离。            |
| `_fallbackHeight`   | `float`     | `1.5`   | 生成扫描点相对于角色原点的高度。                   |

仅在播放模式下运行——它会驱动实时注视系统，因此在 `Unhandled` 编辑模式中会被拒绝。保持的注视会在完成、取消、禁用或销毁时释放。

### 表情套件（`Convai.Modules.Emotion`, `Convai.Modules.BodyLanguage`)

Set Mood 和 React 位于 `SDK/Modules/Emotion/Executors/` ，并且需要一个 `ConvaiEmotionController` 对端。Nod Or Shake Head 位于 `SDK/Modules/BodyLanguage/Executors/` ，并且需要一个 `ConvaiBodyLanguageController` 对端。

#### 设置情绪

持续型：让角色逐渐进入一种新情绪，并保持在那里，直到其他事物将其改变。用于会影响后续整段对话的情绪转变。

| 属性         | 值                                |
| ---------- | -------------------------------- |
| **类**      | `ConvaiSetMoodActionExecutor`    |
| **菜单路径**   | `添加组件 → Convai → Actions → 设置情绪` |
| **原型动作名称** | `设置情绪`                           |
| **目标要求**   | 无                                |
| **所需对端**   | `ConvaiEmotionController`        |

**检查器字段：**

| 字段                   | 类型              | 默认值   | 描述                                        |
| -------------------- | --------------- | ----- | ----------------------------------------- |
| `_defaultMood`       | `string` （情绪标签） | 空     | 角色未指定时使用的情绪。通常 `mood` 参数会驱动这个值。           |
| `_defaultIntensity`  | `float`         | `0.6` | 强度， `0`–`1`。角色可以通过 `intensity` 参数请求不同的时长。 |
| `_transitionSeconds` | `float`         | `1.5` | 变化需要多长时间。                                 |

角色没有的情绪会失败，并列出它实际拥有的情绪——否则情绪系统会把未知情绪当作中性，这样会在什么都没做的情况下报告成功。若要表示瞬时反应，请使用 **反应** 而不是这个；用 Set Mood 来表达短暂一瞬会让角色卡在那个情绪里。

#### 反应

瞬时型：表现一个短暂节拍，保持一下，然后回到角色之前的感受——比如退缩、喜悦闪现、痛苦皱眉。即使动作在中途被取消，恢复也能保证执行。

| 属性         | 值                              |
| ---------- | ------------------------------ |
| **类**      | `ConvaiReactActionExecutor`    |
| **菜单路径**   | `添加组件 → Convai → Actions → 反应` |
| **原型动作名称** | `反应`                           |
| **目标要求**   | 无                              |
| **所需对端**   | `ConvaiEmotionController`      |

**检查器字段：**

| 字段                  | 类型              | 默认值    | 描述                                  |
| ------------------- | --------------- | ------ | ----------------------------------- |
| `_defaultReaction`  | `string` （情绪标签） | 空      | 角色未指定时使用的反应。通常 `reaction` 参数会驱动这个值。 |
| `_defaultIntensity` | `float`         | `0.85` | 强度， `0`–`1`.                        |
| `_holdSeconds`      | `float`         | `1.5`  | 该反应会保持多久，然后再恢复。                     |

角色没有的反应会失败，并列出它实际拥有的反应——理由与 Set Mood 相同。

#### 点头或摇头

用头部作答：点头表示是，摇头表示否，倾斜表示“让我想想”。它叠加在身体当前动作之上，因此不会显得像木偶抽动。

| 属性         | 值                                  |
| ---------- | ---------------------------------- |
| **类**      | `ConvaiHeadResponseActionExecutor` |
| **菜单路径**   | `添加组件 → Convai → Actions → 点头或摇头`  |
| **原型动作名称** | `点头或摇头`                            |
| **目标要求**   | 无                                  |
| **所需对端**   | `ConvaiBodyLanguageController`     |

**检查器字段：**

| 字段           | 类型                                   | 默认值  | 描述                                                     |
| ------------ | ------------------------------------ | ---- | ------------------------------------------------------ |
| `_response`  | `HeadGestureKind` (`点头`, `摇头`, `倾斜`) | `点头` | 角色未指定时使用的响应。角色可以请求 `是`, `否`，或 `也许` ，通过 `回应` 参数请求不同的时长。 |
| `_intensity` | `float`                              | `1`  | 动作幅度有多大， `0`–`1`.                                      |

保持开启直到该手势结束，因此一个序列可以先点头再说话，顺序不会乱。如果头部还在完成上一个手势，执行器会重试最多 1.5 秒，然后失败并返回 `ConvaiActionFailureReason.Busy`.

### 手势套件（`Convai.Modules.BodyAnimation`)

`SDK/Modules/BodyAnimation/Executors/` ——内容驱动：这两个行为都会播放在角色 Animation Set 中编写的剪辑，因此没有这些内容的角色无法执行它们。

#### 而改为使用——这两个行为驱动同一个 Animator，如果一起使用就会互相冲突。

按名称播放角色的某个手势——挥手、耸肩、鞠躬——并在当前姿势上混合进入，再混合退出。

| 属性         | 值                                          |
| ---------- | ------------------------------------------ |
| **类**      | `ConvaiPlayGestureActionExecutor`          |
| **菜单路径**   | `添加组件 → Convai → Actions → 播放手势`           |
| **原型动作名称** | `而改为使用——这两个行为驱动同一个 Animator，如果一起使用就会互相冲突。` |
| **目标要求**   | 无                                          |
| **所需对端**   | `ConvaiBodyAnimationController`            |
| **超时**     | 15s（原型默认值）                                 |

**检查器字段：**

| 字段                | 类型       | 默认值 | 描述                                                    |
| ----------------- | -------- | --- | ----------------------------------------------------- |
| `_defaultGesture` | `string` | 空   | 角色未指定时播放的手势。与 Animation Set 的手势名称及别名进行匹配。             |
| `_holdSeconds`    | `float`  | `8` | 如果某个手势本会无限持续（比如跳舞、思考姿势），则保持它多久。 `0` 会一直保持，直到其他事物将其停止。 |

未知的手势名称会被拒绝为 `Unhandled`；Animation Set 的真实手势名称会在 Detail 追踪详细级别下记录一次。使用普通 Animator Controller 而不是 Body Animation 模块的角色应使用 **播放 Animator 状态** 替代。

#### 指向目标

指向动作所命名的对象，并根据目标实际所在位置选择使用哪只手臂；身体其余部分则继续在底层执行原本动作。

| 属性         | 值                                |
| ---------- | -------------------------------- |
| **类**      | `ConvaiPointAtActionExecutor`    |
| **菜单路径**   | `添加组件 → Convai → Actions → 指向目标` |
| **原型动作名称** | `指向`                             |
| **目标要求**   | 任一                               |
| **所需对端**   | `ConvaiBodyAnimationController`  |
| **超时**     | 15s（原型默认值）                       |

**检查器字段：**

| 字段              | 类型                                    | 默认值    | 描述                                                                  |
| --------------- | ------------------------------------- | ------ | ------------------------------------------------------------------- |
| `_holdSeconds`  | `float`                               | `3`    | 指向保持多久 **在完全伸展时** ——仅仅是手势中间的停顿。                                     |
| `_gestureSpeed` | `float`                               | `1`    | 手臂上抬和下放的速度，以动画自身速度的倍数表示， `0.25`–`3`。不影响 `_holdSeconds`.             |
| `_release`      | `PointingReleaseStyle` (`播放尾段`, `混合`) | `播放尾段` | 保持结束后会发生什么。 `播放尾段` 会让手臂在动画剪辑的剩余部分中放下； `混合` 则直接退出姿势，手势大致会在保持结束时同步结束。 |

{% hint style="warning" %}
**`_holdSeconds` 不再表示整个手势的时长。** 它仅仅是完全伸展时的停顿——手臂的上抬和下放由动画剪辑自身节奏决定，随附的指向剪辑中上下各会增加大约 2.5 秒，所以一个 `_holdSeconds` 的 `1` 仍会产生一个大约 6 秒长的手势。 `_gestureSpeed` 和 `_release` 是本版本新增的，并且可直接控制上抬/下放；两者默认都沿用先前行为，因此现有场景的时序在你调整其中之一前不会改变。设置 `_release` 到 `混合` 为尽可能短的指向。
{% endhint %}

Animation Set 中没有指向剪辑会被拒绝为 `Unhandled`。未解析到目标时也会同样被拒绝——指向始终需要目标。

### 移动套件（`Convai.Modules.BodyAnimation`)

`SDK/Modules/BodyAnimation/Executors/` ——这里的每个行为都需要一个 `ConvaiNavMeshLocomotion` 对端，除了 **转身面向目标**，它不需要 NavMesh。

#### 走向目标

走向目标，会绕开障碍物，并在舒适距离外停下，而不是直接撞到对象上。

| 属性         | 值                                |
| ---------- | -------------------------------- |
| **类**      | `ConvaiWalkToActionExecutor`     |
| **菜单路径**   | `添加组件 → Convai → Actions → 走向目标` |
| **原型动作名称** | `走向`                             |
| **目标要求**   | 任一                               |
| **所需对端**   | `ConvaiNavMeshLocomotion`        |
| **超时**     | 45s（原型默认值）                       |

**检查器字段：**

| 字段                | 类型      | 默认值 | 描述                                                 |
| ----------------- | ------- | --- | -------------------------------------------------- |
| `_arriveDistance` | `float` | `1` | 在距离目标多远处停下，单位为米。角色可以通过 `arriveDistance` 参数请求不同的时长。 |

没有烘焙好的 NavMesh，或者目标不在网格上，都会失败并返回 `ConvaiActionFailureReason.PathBlocked` 并指出目的地。需要烘焙好的 NavMesh。

#### 引导玩家到目标

引导玩家前往某个目的地：先走在前面，玩家落后时停下，追上来后继续前进。

| 属性         | 值                                   |
| ---------- | ----------------------------------- |
| **类**      | `ConvaiLeadPlayerActionExecutor`    |
| **菜单路径**   | `添加组件 → Convai → Actions → 引导玩家到目标` |
| **原型动作名称** | `引导玩家`                              |
| **目标要求**   | 任一                                  |
| **所需对端**   | `ConvaiNavMeshLocomotion`           |
| **超时**     | 120秒（原型默认值）                         |

**检查器字段：**

| 字段                      | 类型      | 默认值   | 描述                        |
| ----------------------- | ------- | ----- | ------------------------- |
| `_arriveDistance`       | `float` | `1.4` | 角色停在离目的地多远的地方。            |
| `_waitWhenFartherThan`  | `float` | `4.5` | 当玩家距离超过此值时暂停旅程。           |
| `_resumeWhenCloserThan` | `float` | `2.8` | 一旦玩家回到此距离内，就恢复旅程。         |
| `_maximumWaitSeconds`   | `float` | `12`  | 在没有玩家的情况下继续前往目的地前的最长等待时间。 |

场景中没有玩家时失败，错误为 `ConvaiActionFailureReason.TargetMissing`。无法到达目的地的路径失败，错误为 `PathBlocked`.

#### 转身面向目标

原地转身面向目标，而不朝它走去——大多数时候，“看向顾客”指的就是这个，而不是穿过整个房间。无需 NavMesh。

| 属性         | 值                                |
| ---------- | -------------------------------- |
| **类**      | `ConvaiTurnToFaceActionExecutor` |
| **菜单路径**   | `添加组件 → Convai → 操作 → 转向面向目标`    |
| **原型动作名称** | `转向面向`                           |
| **目标要求**   | 任一                               |
| **所需对端**   | `ConvaiBodyAnimationController`  |
| **超时**     | 10s（原型默认值）                       |

**检查器字段：**

| 字段                   | 类型                                                   | 默认值            | 描述                                                                                   |
| -------------------- | ---------------------------------------------------- | -------------- | ------------------------------------------------------------------------------------ |
| `_turnStyle`         | `ConvaiTurnStyle` (`SteppingTurn`, `SmoothRotation`) | `SteppingTurn` | `SteppingTurn` 播放角色自己的转身动画； `SmoothRotation` 直接旋转，耗时 `_smoothTurnSeconds` 并且不需要动画片段。 |
| `_smoothTurnSeconds` | `float`                                              | `0.5`          | 一个……的持续时间 `SmoothRotation` 转身。被……忽略 `SteppingTurn`.                                  |
| `_toleranceDegrees`  | `float`                                              | `8`            | 面向目标到什么程度才算完成， `0`–`45`.                                                             |

`SteppingTurn` 在动画集里没有转身片段时会退化为 `Unhandled`，并将 `SmoothRotation` 作为替代。

#### 跟随玩家

“跟我来。”保持舒适距离，玩家走开时缩短间距，玩家停下时原地站立。

| 属性         | 值                                  |
| ---------- | ---------------------------------- |
| **类**      | `ConvaiFollowPlayerActionExecutor` |
| **菜单路径**   | `添加组件 → Convai → 操作 → 跟随玩家`        |
| **原型动作名称** | `跟随玩家`                             |
| **目标要求**   | 无（玩家是隐含的）                          |
| **所需对端**   | `ConvaiNavMeshLocomotion`          |

**检查器字段：**

| 字段                | 类型                              | 默认值   | 描述                                              |
| ----------------- | ------------------------------- | ----- | ----------------------------------------------- |
| `_mode`           | `ConvaiFollowMode` (`按照`, `停止`) | `按照`  | 此调用是开始跟随还是停止。角色可以通过 `模式` 参数（`follow` 或 `stop`). |
| `_followDistance` | `float`                         | `2.2` | 角色试图与玩家保持的距离。                                   |
| `_slack`          | `float`                         | `0.8` | 玩家必须移动超过 `_followDistance` 角色才会缩短间距。            |

{% hint style="info" %}
**跟随没有自然结束。** 角色一开始跟随，该动作就会报告成功，而跟随本身会继续进行——否则它会一直保持打开状态，直到超时，并阻塞之后的每个动作。再次发送该动作，并将 `mode: stop`，或者禁用角色，来结束它。正在跟随的角色仍会响应其他移动动作（Walk To Target、Return To Start）：在任何不是它下达的移动执行期间，跟随会暂时让位，而在该移动结束后又会重新回到玩家身边继续跟随。
{% endhint %}

未找到玩家时失败，错误为 `ConvaiActionFailureReason.TargetMissing`.

#### 返回起始位置

走回角色开始的位置——或者你选择的位置——并可选地恢复原来的朝向。此包中其他所有内容的撤销操作。

| 属性         | 值                                   |
| ---------- | ----------------------------------- |
| **类**      | `ConvaiReturnToStartActionExecutor` |
| **菜单路径**   | `添加组件 → Convai → 操作 → 返回起始位置`       |
| **原型动作名称** | `返回起始位置`                            |
| **目标要求**   | 无                                   |
| **所需对端**   | `ConvaiNavMeshLocomotion`           |

**检查器字段：**

| 字段                 | 类型          | 默认值    | 描述                         |
| ------------------ | ----------- | ------ | -------------------------- |
| `_homeSpot`        | `Transform` | `null` | “回去”指哪里。留空则使用场景开始时角色站立的位置。 |
| `_restoreFacing`   | `bool`      | `true` | 到达后转回原来的朝向。                |
| `_turnBackSeconds` | `float`     | `0.6`  | 最后那次转身要花多久。                |
| `_arriveDistance`  | `float`     | `0.2`  | 离多近才算到家。                   |

起始位置记录在 `Awake`中，在角色的其他任何内容能移动它之前。无法返回的路径失败，错误为 `PathBlocked`.

### 观察包（`Convai.Runtime`)

`SDK/Runtime/Actions/Executors/` ——本次发布中的新包。两种行为都通过 `ConvaiActionExecutionResult.Answered` 返回答案，并使用 `AnswerDelivery = TellThePlayer` 作为默认值，因此除非你更改该动作的 **完成时** 设置，否则角色会说出结果。

#### 统计目标组

统计一个 `ConvaiActionTargetGroup` 中已启用成员的数量，并用结果回答——“还剩多少箱子。”

| 属性         | 值                                            |
| ---------- | -------------------------------------------- |
| **类**      | `ConvaiCountTargetGroupActionExecutor`       |
| **菜单路径**   | `添加组件 → Convai → 操作 → 统计目标组`                 |
| **原型动作名称** | `统计目标组`                                      |
| **目标要求**   | 对象                                           |
| **所需目标组件** | `ConvaiActionTargetGroup`，位于解析后的目标对象上（不在角色上） |

**检查器字段：**

| 字段                      | 类型       | 默认值    | 描述                              |
| ----------------------- | -------- | ------ | ------------------------------- |
| `_availableMembersOnly` | `bool`   | `true` | 计数时忽略已禁用的成员组件和非活动的成员对象。         |
| `_includeMemberNames`   | `bool`   | `true` | 在答案中包含成员名称以及数量。                 |
| `_memberLabel`          | `string` | 空      | 可选复数标签，例如 `“箱子”`。留空则使用目标组自己的名称。 |

解析出的目标若没有 `ConvaiActionTargetGroup` 组件，或者是空组，则会被拒绝，错误为 `Unhandled` 而不是报告一个容易误导的零。

#### 测量距离

测量角色到目标的地面平面距离；如果未指定目标，则测量到玩家的距离，并用通俗说法回答——“大约 3 米远。”

| 属性         | 值                                     |
| ---------- | ------------------------------------- |
| **类**      | `ConvaiMeasureDistanceActionExecutor` |
| **菜单路径**   | `添加组件 → Convai → 操作 → 测量距离`           |
| **原型动作名称** | `测量距离`                                |
| **目标要求**   | 任一                                    |
| **所需对端**   | 无                                     |

**检查器字段：**

| 字段                   | 类型      | 默认值    | 描述                                   |
| -------------------- | ------- | ------ | ------------------------------------ |
| `_withinReachMetres` | `float` | `1.2`  | 不超过此值的距离会被描述为“伸手可及”。                 |
| `_aFewStepsMetres`   | `float` | `3.5`  | 不超过此值的距离会被描述为“几步之外”。                 |
| `_acrossAreaMetres`  | `float` | `9`    | 不超过此值的距离会被描述为“隔着这个区域”。超过此值则为：“很远很远。” |
| `_includeMetres`     | `bool`  | `true` | 在答案中包含以米为单位的测量值。                     |

场景中没有目标也没有玩家时失败，错误为 `ConvaiActionFailureReason.TargetMissing`.

### 选择合适的执行器

| 使用场景                               | 推荐的执行器                                                                                                                  |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 无需代码即可接入现有玩法                       | 触发 Unity 事件                                                                                                             |
| 为一系列动作设定节奏，或在步骤之间暂停                | 等待                                                                                                                      |
| 将多个行为串联为一个动作                       | 按顺序运行                                                                                                                   |
| 切换场景对象的可见性                         | 显示或隐藏对象                                                                                                                 |
| 角色使用自己的 Animator Controller 进行动画播放 | 播放 Animator 状态                                                                                                          |
| 播放一次性声音，可带目标也可不带                   | 通过普通的                                                                                                                   |
| 将角色的视线转向目标                         | 注视目标                                                                                                                    |
| 按需与玩家保持眼神接触                        | 注视玩家                                                                                                                    |
| 明显地环顾周围区域                          | 扫描环境                                                                                                                    |
| 改变角色当前持续的情绪状态                      | 设置情绪                                                                                                                    |
| 转瞬即逝的情绪瞬间                          | 反应                                                                                                                      |
| 用头部表示是、否或“让我想想”                    | 点头或摇头                                                                                                                   |
| 播放动画集中名为某个名称的手势                    | 而改为使用——这两个行为驱动同一个 Animator，如果一起使用就会互相冲突。                                                                                |
| 指向指定的人、地点或物体                       | 指向目标                                                                                                                    |
| 使用寻路导航到目标                          | 走向目标                                                                                                                    |
| 引导玩家前往某处                           | 引导玩家到目标                                                                                                                 |
| 原地转身面向目标                           | 转身面向目标                                                                                                                  |
| 在玩家移动时陪同他们                         | 跟随玩家                                                                                                                    |
| 撤销移动——走回起点                         | 返回起始位置                                                                                                                  |
| 统计可用的已知对象数量                        | 统计目标组                                                                                                                   |
| 回答“那有多远”                           | 测量距离                                                                                                                    |
| 未随游戏发布的执行器覆盖的内容                    | [编写自定义动作执行器](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/writing-custom-executors.md) |

### 下一步

{% content-ref url="/pages/6e3c85bad169c9c2c755b38be39008ef3ce023cf" %}
[分发器和批处理策略](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/dispatcher-and-batch-policies.md)
{% endcontent-ref %}

{% content-ref url="/pages/c5598abd0ddd72fa75a0989ad602a5b4d12e16d7" %}
[编写自定义动作执行器](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/writing-custom-executors.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/character-actions/action-executors.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.
