> 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/unreal-engine-plugin-beta-overview/convai-actions/phase-3-parameterized-actions.md).

# 阶段 3：带参数的动作

为自定义动作提供带类型的输入——数字、Actor 引用和受约束的选项——并在 Blueprint 处理程序中读取解析后的值。

第 2 阶段新增了一个无参数的自定义动作。大多数真实动作都需要携带数据—— *“等待 5 秒”*, *“捡起立方体”*, *“把球放在桌子上”*。本阶段将讲解：

1. 一个简单的数值参数（`Wait For` 已回顾）。
2. 一个角色引用（单个参数解析为一个 `AActor*`).
3. 一个带两个参数 + 一个连接词的复合动作（`Put ... on ...`).
4. 通过以下方式约束值： `Choices` （手动列表）和 `Enum` （来自一个 `UENUM`).
5. 实时编辑器预览——既可作为调试辅助，也可直接用来编写模板。

### 参数类型矩阵

每个 `FConvaiActionParam` 都有一个 **`Type`** ，它同时决定发送给 LLM 的线格式提示，以及解析器如何解释响应：

| Type          | 线格式提示     | 解析器                                                  |
| ------------- | --------- | ---------------------------------------------------- |
| **Auto**      | （无）       | 尝试 Reference → Number → Bool → 最后回退到 String。新参数的默认值。 |
| **Reference** | `：ref`    | 根据以下内容查找该值： `Environment.Objects` 然后 `.Characters`.  |
| **String**    | `：string` | 按文本处理。                                               |
| **Number**    | `：number` | `Atof`.                                              |
| **Bool**      | `：bool`   | `true` 用于“true”/“yes”/“1”，否则为 false。                 |
| **Enum**      | `：enum`   | 约束为一个 `UEnum` 你选择的（自动填充 `Choices`).                  |

> 无论声明的类型是什么， **上的所有值字段都会 `FConvaiResultParam` 尽力填充**。一个 `String`类型的参数，即使其值恰好是场景中某个 Object 的名称，也仍然会有 `RefValue` 被设置。读取你方便的字段即可—— `Type` 它只表示 LLM 想把哪个槽位当作目标。

### 示例 A——一个数值参数

我们会重做 `Wait For` ，以端到端展示 typed-param 流程。

#### 声明模板

1. 选择 Convai chatbot，打开 **Environment → Actions**.
2. 随附的 **`Wait For`** 条目已经有一个参数 `秒数` 已类型化 `Number` 并带有描述 *“等待多长时间，以秒为单位”*。可直接使用，或添加你自己的。

渲染后的预览（会自动填充到结构化字段下方）显示为：

```
Wait For "<time in seconds: number>" — 等待一段时长。time in seconds: 等待多长时间，以秒为单位。
```

这个 `：number` 提示告诉 LLM 返回一个数值。 `"<...>"` 引号包裹告诉它把响应值用双引号输出，这样即使值中包含空格，解析器也能无歧义地拆分。

#### 在 BP 中读取参数

在你的 `OnActionReceivedEvent_V2` 处理器里的 `Wait For` switch case：

1. 拖出一个 **`Get Param As Number`** 节点，连接到 chatbot 引用。
   * **Action**：循环中的当前 `FConvaiResultAction` 。
   * **Name**: `秒数`.
2. 把返回的 `float` 连接到一个 **`Delay (Duration)`** 节点。
3. 延迟结束后，调用 `Handle Action Completion(true, 0, EventText="Done waiting", ShouldRespond=Auto)`.

这个 `EventText` 参数可让你告诉机器人 *“那已经完成了”* ，并在同一次调用中完成——这对于在不单独使用 `Add Context Event`.

#### 测试

提问： *“等待 3 秒。”* 机器人应该暂停，然后说 *“Done waiting”* 或类似的话（取决于 `ShouldRespond` 以及 LLM 的心情）。

### 示例 B——一个角色引用

`Move To` 使用随附默认值时已经这样做了，但这里给出自定义版本的配方。

#### 声明

添加一个动作 `Greet` ，带一个参数：

* **Name**: `target`
* **Type**: `Reference`
* **Description**: `要问候谁`

预览变为：

```
Greet "<target: ref>" — <action description if any>. target: 要问候谁。
```

#### 在 BP 中读取

1. **`Get Param As Ref`** 使用 `Name = "target"` 返回一个 `FConvaiObjectEntry`。 `Ref` 字段是解析后的 `AActor*` （因为该值匹配了 `Environment.Objects` 或 `.Characters`).
2. 使用该角色——让它面向对方、播放动画，或者按你的 `Greet` 需要来。

### 示例 C——一个带连接词的复合动作

*“把球放在桌子上”* 可以很自然地建模为两个 `Reference` 参数，以及第二个参数的连接词：

#### 声明

Action `Put`，两个参数：

| Name    | Type      | 连接词        | Description |
| ------- | --------- | ---------- | ----------- |
| `ball`  | Reference | （空——第一个参数） | 要捡起什么       |
| `table` | Reference | `on`       | 放在哪里        |

预览：

```
Put "<ball: ref>" on "<table: ref>" — 将一个对象放到另一个对象上。ball: 要捡起什么。table: 放在哪里。
```

这个 `连接词` 字段 **不** 仅限于介词——它是“任何将参数与前文连接起来的文本”。 `到`, `使用`, `使用`, `用于`等都可以。

#### 在 BP 中读取

```
Get Param As Ref(action, "ball")  → FConvaiObjectEntry（球）
Get Param As Ref(action, "table") → FConvaiObjectEntry（桌子）
```

只要 LLM 选择的名称与你的 `Ref` 匹配，两者的 `Environment.Objects`.

### 示例 D——受约束的值（Choices）

如果你希望 LLM 从一个 **固定列表**中选择，填充 `Choices`:

#### 声明

Action `Set Mood`，一个参数：

* **Name**: `mood`
* **Type**: `String`
* **Description**: `机器人应该是什么感受`
* **Choices**: `happy`, `sad`, `angry`

预览：

```
Set Mood "<mood [happy|sad|angry]: string>" — 设置机器人的心情。mood: 机器人应该是什么感受。
```

这个 `[choices]` 线格式中的块会对 LLM 进行约束。解析器在接收时也会根据列表进行校验——不在集合中的值仍会进入结果，但会记录警告。

### 示例 E——Enum 类型的值

当你的 Blueprint 已经有一个 `UENUM` 你想使用的时，将参数 **Type** 到 **`Enum`**&#x5207;换过去。Details 面板会隐藏手动 `Choices` 字段，并显示一个 **`Enum Type`** 选择器。

#### 声明

```cpp
UENUM(BlueprintType)
enum class EBotMood : uint8 { Happy, Sad, Angry };
```

Action `Set Mood`，一个参数：

* **Type**: `Enum`
* **Enum Type**: `EBotMood`
* **Name** / **Description**：与之前相同。

预览：

```
Set Mood "<mood [Happy|Sad|Angry]: enum>" — 设置机器人的心情。mood: 机器人应该是什么感受。
```

选项块会根据 enum 的显示名称自动生成。如果你忘了设置 `Enum Type`，预览会嵌入 `[ERROR: EnumType not set]` 内联显示，这样在编辑时就能明显看出配置错误。

#### 在 BP 中读取

`Get Param As String(action, "mood")` 返回 `“Happy”` / `“Sad”` / `“Angry”`。使用以下方式将其转换为 enum 值： **`Convert String to Byte`** 或 UE 为 `EBotMood`.

### 渲染后的字符串——调试 + 编写

这个 **`Rendered String`** 字段在每个 `FConvaiAction` 上是一个可双向同步的多行文本框：

* **读取它** 可以准确看到发送给 LLM 的内容。适用于：
  * 在连接之前检查说明是否合理。
  * 复制到单独的工具中测试不同的提示变体。
  * 并排比较两个角色的动作契约。
* **写入它** ，结构化字段就会更新。插件会将格式解析回 `Name <connector> "<param: type>"… — Description. param: desc.` 并回填到 Name / Description / Parameters 中。这在以下情况下很有用：
  * 在不同角色之间复制模板。
  * 无需在嵌套结构字段中滚动即可快速编辑长描述。

> **如果你的编辑无法被干净解析** （括号损坏、类型词无法识别等），预览会在下一次刷新时静默回退为结构化字段的规范渲染。只要遵守格式规则就没问题。

双向同步是保守的：只有当渲染字符串与结构化字段应生成的内容实际不同的时候才会重新解析，因此偶发的提交（焦点变化、误点击）不会降级类型。

### 从旧字段迁移

如果你有较旧的处理器图表在读取 `FConvaiResultAction.RelatedObjectOrCharacter` 或 `.ConvaiExtraParams.Number/Text`，它们仍然可以编译——这些字段会作为新 `Parameters` 映射的已弃用镜像而被填充。BP 节点提示会显示指向替代项的弃用信息：

| 旧版                                    | 新版                                                              |
| ------------------------------------- | --------------------------------------------------------------- |
| `Result.RelatedObjectOrCharacter.Ref` | `Get Param As Ref(action, "<name>").Ref` （或 `Get First Param`). |
| `Result.ConvaiExtraParams.Number`     | `Get Param As Number(action, "<name>")`.                        |
| `Result.ConvaiExtraParams.Text`       | `Get Param As String(action, "<name>")`.                        |
| `Get Action Param(extraParams, name)` | `Get Param As String(action, name)`.                            |

你可以按处理器逐个迁移，按自己的节奏来；没有什么会强迫你立刻重写。

### 接下来去哪里

你现在已经知道：

* 参数类型矩阵以及它生成的线格式。
* 如何用连接词构建复合动作。
* 如何通过 `Choices` 或 `Enum`.
* 如何通过 typed 访问器在 Blueprint 中读取参数。
* 如何使用渲染预览进行调试或直接编写。

这就是全部的动作编写界面。关于驱动一切的运行时契约（四条服务器提示通道、动态上下文管线、场景元数据更新、对话对象、注视目标），请参阅插件内参考： **`Convai/Docs/ActionsAndEnvironment.md`** 以及更深入的 V2 参考： **`Convai/Docs/ActionsV2.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/unreal-engine-plugin-beta-overview/convai-actions/phase-3-parameterized-actions.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.
