> 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).

# 动作执行器

执行器是在调度器运行动作步骤时执行场景内行为的组件。Convai SDK 附带七个执行器组件。本页记录了每个 Inspector 字段，并说明何时使用各个执行器。

#### LookAtTargetActionExecutor

在可配置的持续时间内平滑旋转 NPC 使其面向已解析的目标。使用 `Quaternion.Slerp` 并遵守取消。

| 属性       | 值                                                          |
| -------- | ---------------------------------------------------------- |
| **菜单路径** | `添加组件 → Convai → Actions → Look At Target Action Executor` |
| **命名空间** | `Convai.Runtime.Actions`                                   |
| **需要目标** | 是——返回 `未处理` 如果未解析到目标                                       |

**Inspector 字段：**

| 字段            | 类型          | 默认值    | 描述                                 |
| ------------- | ----------- | ------ | ---------------------------------- |
| `_rotateRoot` | `Transform` | `null` | 要旋转的变换。如果未指定，则使用组件自身的 `transform`. |
| `_duration`   | `float`     | `0.5`  | 完成旋转所需的秒数。 `0` 会立即跳转。              |

**行为：** 执行器会在……期间从当前旋转逐渐插值到朝向目标位置。 `_duration` 秒。如果根对象或目标在执行过程中被销毁，则返回 `失败`.

#### UnityEventActionExecutor

触发一个 `UnityEvent` 并立即返回 `成功`。不需要目标解析。可用它在无需编写代码的情况下，将任何后端动作连接到 Inspector 绑定的回调——切换门、播放声音、打开 UI 面板。

| 属性       | 值                                                       |
| -------- | ------------------------------------------------------- |
| **菜单路径** | `添加组件 → Convai → Actions → Unity Event Action Executor` |
| **命名空间** | `Convai.Runtime.Actions`                                |
| **需要目标** | 未                                                       |

**Inspector 字段：**

| 字段           | 类型           | 描述                                   |
| ------------ | ------------ | ------------------------------------ |
| `_onExecute` | `UnityEvent` | 每次动作步骤运行时调用。可在 Inspector 中绑定任意数量的回调。 |

{% hint style="danger" %}
**`TransformMoveToActionExecutor` 仅用于原型设计。** 它会瞬间传送角色，没有动画或寻路。请在发布给用户之前将其替换为 `NavMeshMoveToActionExecutor` 或自定义执行器。
{% endhint %}

#### TransformMoveToActionExecutor

立即将 NPC 的 transform 贴到已解析目标的位置，并加上一个可选偏移。同步——在一帧内完成。

| 属性       | 值                                                             |
| -------- | ------------------------------------------------------------- |
| **菜单路径** | `添加组件 → Convai → Samples → Transform Move To Action Executor` |
| **命名空间** | `Convai.Sample.Behaviors`                                     |
| **需要目标** | 是——返回 `失败` 如果未解析到目标                                           |

**Inspector 字段：**

| 字段          | 类型          | 默认值         | 描述                                 |
| ----------- | ----------- | ----------- | ---------------------------------- |
| `_moveRoot` | `Transform` | `null`      | 要移动的变换。如果未指定，则移动组件自身的 `transform`. |
| `_offset`   | `Vector3`   | `(0, 0, 0)` | 应用到目标位置的世界空间偏移。可用于在目标前方稍微停下。       |

#### NavMeshMoveToActionExecutor

驱动一个 `NavMeshAgent` 前往已解析目标的位置，并等待代理到达停止距离。动作步骤会保持激活直到到达，这意味着调度器会在导航完成前暂停下一步。

| 属性       | 值                                                           |
| -------- | ----------------------------------------------------------- |
| **菜单路径** | `添加组件 → Convai → Samples → NavMesh Move To Action Executor` |
| **命名空间** | `Convai.Sample.Behaviors`                                   |
| **需要目标** | 是——返回 `失败` 如果未解析到目标                                         |

**Inspector 字段：**

| 字段                  | 类型             | 默认值   | 描述                                                      |
| ------------------- | -------------- | ----- | ------------------------------------------------------- |
| `_agent`            | `NavMeshAgent` | 自动解析  | 该 `NavMeshAgent` 要驱动的。若未指定，则从同一 `GameObject` 于 `Awake`. |
| `_stoppingDistance` | `float`        | `0.5` | 代理被视为到达时的世界单位距离。                                        |

{% hint style="warning" %}
此执行器才能导航前，场景中必须有已烘焙的 NavMesh。打开 **窗口 → AI → 导航** 并在进入播放模式前烘焙。执行器在以下情况下返回 `失败` 如果代理被禁用、不在 NavMesh 上，或 `SetDestination` 失败——它不会等待 `TimeoutSeconds` 在这些情况下超时。
{% endhint %}

#### AnimatorTriggerActionExecutor

通过可配置的绑定列表，将后端动作名称映射到 Animator 的触发器参数。触发该参数并立即返回 `成功` ——它不会等待动画结束。

| 属性       | 值                                                            |
| -------- | ------------------------------------------------------------ |
| **菜单路径** | `添加组件 → Convai → Samples → Animator Trigger Action Executor` |
| **命名空间** | `Convai.Sample.Behaviors`                                    |
| **需要目标** | 未                                                            |

**Inspector 字段：**

| 字段          | 类型                                   | 默认值  | 描述                                                  |
| ----------- | ------------------------------------ | ---- | --------------------------------------------------- |
| `_animator` | `Animator`                           | 自动解析 | 该 `Animator` 要驱动的。若未指定，则从同一 `GameObject` 于 `Awake`. |
| `_bindings` | `List<AnimatorTriggerActionBinding>` | 为空   | 将动作名称映射为触发器名称。每个条目都有两个字符串字段（见下文）。                   |

**AnimatorTriggerActionBinding 字段：**

| 字段            | 类型       | 描述                                                              |
| ------------- | -------- | --------------------------------------------------------------- |
| `ActionName`  | `string` | 要匹配的动作名称（不区分大小写）。必须匹配以下内容中的一项： `ConvaiActionConfigSource`的动作定义。 |
| `TriggerName` | `string` | 当动作匹配时要触发的 Animator 触发器参数。必须与 Animator Controller 中的触发器名称完全一致。  |

**绑定列表示例：**

| ActionName | TriggerName     |
| ---------- | --------------- |
| `挥手`       | `TriggerWave`   |
| `敬礼`       | `TriggerSalute` |
| `指向`       | `TriggerPoint`  |

如果没有绑定匹配传入的动作名称，执行器将返回 `失败` 并返回消息 `未找到 '<action name>' 的绑定`。如果没有 `Animator` 被解析到，则返回 `失败` 并返回消息 `Animator not assigned` 作为替代。

#### PickUpActionExecutor

复合执行器，串联三个行为：导航到目标 → 触发动画触发器 → 等待动画 → 将对象附加到手部变换。该步骤会一直保持激活，直到这三个阶段全部完成。

| 属性       | 值                                                   |
| -------- | --------------------------------------------------- |
| **菜单路径** | `添加组件 → Convai → Samples → Pick Up Action Executor` |
| **命名空间** | `Convai.Sample.Behaviors`                           |
| **需要目标** | 是——返回 `失败` 如果未解析到目标                                 |

**Inspector 字段：**

| 字段                   | 类型                            | 默认值        | 描述                                                                                                                                                     |
| -------------------- | ----------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `_mover`             | `NavMeshMoveToActionExecutor` | 必需         | 驱动到目标的导航。必须赋值——若为 `失败` null 则返回。                                                                                                                       |
| `_animator`          | `Animator`                    | `null`     | 要驱动的 Animator。可选——如果为 null 或如果 `_pickUpTrigger` 为空，则跳过。                                                                                                |
| `_pickUpTrigger`     | `string`                      | `"PickUp"` | 到达目标后要触发的 Animator 触发器参数。                                                                                                                              |
| `_attachPoint`       | `Transform`                   | `null`     | 被拾取对象要重新设置父级到的变换（例如手部骨骼）。如果存在 `HeldObjectActionState` 并且未设置附着点，则将此值赋给它；否则目标将直接重新设父到 `_attachPoint` 。可选——如果为 null 且没有 `HeldObjectActionState` 则不会重新设父级。 |
| `_animationDuration` | `float`                       | `1.0`      | 触发动画触发器后，在重新设父对象前等待的秒数。以下情况会跳过： `0` 或更少。                                                                                                               |

**执行顺序：**

1. 如果未解析到目标，则返回 `失败` 并返回消息 `未解析到目标`.
2. 如果存在一个 `HeldObjectActionState` 组件位于同一个 `GameObject`，会检查它是否已经持有对象：如果已经持有目标，则立即返回 `成功` 如果持有的是其他对象，则返回 `失败` 如果持有的是不同对象。
3. `NavMeshMoveToActionExecutor.ExecuteAsync` 导航到目标。如果未成功， `PickUpActionExecutor` 则立即返回该结果。
4. 如果 `_animator` 已赋值且 `_pickUpTrigger` 不为空， `_animator.SetTrigger(_pickUpTrigger)` 则会被调用。
5. 等待 `_animationDuration` 秒（可取消），以下情况会跳过： `_animationDuration` 是 `0` 或更少。
6. 附加目标：如果存在一个 `HeldObjectActionState` 则 `HeldObjectActionState.TryAttach` 会重新设置其父级（使用 `_attachPoint` 在状态没有附着点时先设置状态的附着点）。否则目标会直接重新设父到 `_attachPoint` 处，局部位置/旋转为零；如果 `_attachPoint` 为 null，则跳过。
7. 返回 `成功`.

`PickUpActionExecutor` 会调用 `NavMeshMoveToActionExecutor` 直接通过 `ExecuteAsync`。这两个组件应位于同一个 `GameObject` —— `_mover` 是普通的 Inspector 引用，不会自动解析——并且场景中必须存在已烘焙的 NavMesh。添加一个可选的 `HeldObjectActionState` 组件（`添加组件 → Convai → Samples → Held Object Action State`）到同一个 `GameObject` 以在拾取和放下动作之间跟踪当前持有的对象，并阻止 NPC 在已持有一个对象时拾取第二个对象。

#### PutOnActionExecutor

将一个已解析的目标对象放到另一个对象上。不同于其他执行器，它不会解析单个主目标——而是从后端命令中绑定两个命名参数， `项目` 和 `Container`，每个都解析为一个 `ConvaiResolvedActionTarget`.

| 属性       | 值                                                  |
| -------- | -------------------------------------------------- |
| **菜单路径** | `添加组件 → Convai → Samples → Put On Action Executor` |
| **命名空间** | `Convai.Sample.Behaviors`                          |
| **需要目标** | 没有单一目标——而是解析 `项目` 和 `Container` 参数                 |

**Inspector 字段：**

| 字段                 | 类型        | 默认值           | 描述                   |
| ------------------ | --------- | ------------- | -------------------- |
| `_placementOffset` | `Vector3` | `(0, 0.5, 0)` | 放置物品时添加到容器位置的世界空间偏移。 |

如果 `项目` 或 `Container` 未解析为一个 `GameObject`，则执行器返回 `失败` 并返回消息 `物品未解析。` 或 `容器未解析。` 分别对应。否则，它会清除物品在任何 `HeldObjectActionState` 上的 `GameObject` （如果存在），并将物品的 transform 移动到容器的位置加上 `_placementOffset`，然后返回 `成功`.

### 选择合适的执行器

| 使用场景                  | 推荐执行器                                                                                                                   |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| NPC 平滑面向目标            | `LookAtTargetActionExecutor`                                                                                            |
| 任何无需目标且连接到游戏回调的动作     | `UnityEventActionExecutor`                                                                                              |
| 无需 NavMesh 的快速原型开发    | `TransformMoveToActionExecutor`                                                                                         |
| 带寻路的生产级 NPC 移动        | `NavMeshMoveToActionExecutor`                                                                                           |
| 为不同动作播放不同动画           | `AnimatorTriggerActionExecutor`                                                                                         |
| 一次命令中完成导航 + 拾取 + 附加   | `PickUpActionExecutor`                                                                                                  |
| 将一个已持有或场景中的对象放到另一个对象上 | `PutOnActionExecutor`                                                                                                   |
| 自定义移动系统、背包、UI、物理      | [编写自定义动作执行器](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/writing-custom-executors.md) |

### 使用示例

#### 示例 1——带手势和移动的安全培训员

**场景：** 一个工作场所安全培训模拟。讲师 NPC 使用两个始终可用的执行器来指向危险并演示设备位置。

**NPC 上的 Inspector 设置：**

* `LookAtTargetActionExecutor` —— `_duration = 0.8`
* `UnityEventActionExecutor` —— `_onExecute` → 调用 `HazardHighlightManager.HighlightActive()`

**ConvaiActionConfigSource 定义：**

| ActionName | 目标要求   | 执行器                          |
| ---------- | ------ | ---------------------------- |
| `指向`       | `任意一个` | `LookAtTargetActionExecutor` |
| `标记危险`     | `无`    | `UnityEventActionExecutor`   |

**预期结果：** "指向燃气阀门" → NPC 会在 0.8 秒内转向并面对燃气阀门。"标记危险" → the `UnityEvent` 会触发并在 UI 中高亮当前危险。

#### 示例 2——带动画的设备取回

**场景：** 一个医疗培训场景。讲师取回除颤器并将其递交出去。

**Inspector 设置：**

* `NavMeshMoveToActionExecutor` —— `_stoppingDistance = 0.6`
* `PickUpActionExecutor` —— `_mover = NavMeshMoveToActionExecutor`, `_pickUpTrigger = "GrabItem"`, `_attachPoint = RightHandBone`, `_animationDuration = 1.2`

**ConvaiActionConfigSource 定义：**

| ActionName | 目标要求 | 执行器                    |
| ---------- | ---- | ---------------------- |
| `取回`       | `对象` | `PickUpActionExecutor` |

**预期结果：** "取回除颤器" → NPC 导航到除颤器，播放 1.2 秒的抓取动画，然后除颤器附加到右手骨骼上。

### 下一步

{% 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.
