> 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/update-actions-at-runtime.md).

# 在运行时更新角色动作

使用 `ConvaiActionConfigPatch` 和 `ConvaiCharacter.DynamicContext.Apply` 用于替换已连接角色的动作、对象、角色或注意目标，而无需断开会话。当连接后场景状态发生变化——出现了新对象，或某个目标变得不可用——且角色的可执行能力需要跟上时使用此功能。只有在 Convai 就其更新 ID 返回成功确认后，此补丁才会生效。

### 前提条件

* 某个 `ConvaiCharacter` 已连接（`IsInConversation` 返回 `true`).
* 本地 `ConvaiActionDefinition` 对于补丁添加的任何操作名称，条目已经注册——补丁中的操作名称必须匹配本地可执行定义，无论它来自内联定义还是可复用的 Action Set（参见 [配置角色动作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/configuring-actions.md)），否则整个更新在发送前就会被拒绝。
* 熟悉 [配置角色动作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/configuring-actions.md).

### 发送运行时操作补丁

{% stepper %}
{% step %}

#### 构建补丁

只设置你想更改的字段。 `ConvaiActionConfigPatch` 使用省略与空值语义： `null` 字段会保留已确认的值，空列表或空字符串会清除它，而非空值会替换它。

```csharp
using System.Collections.Generic;
using Convai.Shared.Actions;

var patch = new ConvaiActionConfigPatch
{
    Objects = new List<ConvaiActionObjectDefinition>
    {
        new()
        {
            Name = "杠杆",
            Description = "金属墙壁拉杆。",
            GameObjectReference = leverGameObject
        }
    }
};
```

| 字段           | `null` （省略） | 空列表或字符串 | 非空值                                                   |
| ------------ | ----------- | ------- | ----------------------------------------------------- |
| `动作`         | 保留已确认的操作列表  | 清除请求级操作 | 替换已确认的操作列表                                            |
| `对象`         | 保留已确认对象     | 清除已确认对象 | 替换已确认对象。同名替换会继承现有的本地 `GameObjectReference` 当新条目未设置该值时 |
| `Characters` | 保留已确认角色     | 清除已确认角色 | 替换已确认角色                                               |
| `当前注意对象`     | 保留注意目标      | 清除注意目标  | 设置注意目标。必须与以下名称中的一个匹配： `对象` 在替换应用后                     |

替换 `对象` 如果该目标不再存在，替换会自动清除过期的注意目标。
{% endstep %}

{% step %}

#### 发送补丁

将补丁传递给 `DynamicContext.Apply` 配合明确的 `updateId` 以便你关联后端确认：

```csharp
using Convai.Runtime;
using Convai.Runtime.DynamicContext;

character.DynamicContext.Apply(new ConvaiDynamicContextUpdate(
    text: null,
    reaction: ConvaiRespondMode.Silent,
    currentAttentionObject: "杠杆",
    updateId: "lever-unlock-01",
    actionConfig: patch));
```

{% hint style="warning" %}
发送补丁不会立即更改 `ConvaiCharacter.ActionConfig` 立即生效。确认按更新发送的顺序提交。错误状态、不匹配的确认、断开连接或 30 秒确认超时会丢弃待处理的变更，不会重试它—— `ActionConfig` 始终反映最近一次后端确认的快照，而不是你发送的最新补丁。
{% endhint %}
{% endstep %}
{% endstepper %}

### 跟踪更新 ID

提供你自己的 `updateId` 在 `ConvaiDynamicContextUpdate` 而不是依赖 SDK 自动生成的那个。当 `updateId` 被省略时，SDK 会生成一个用于跟踪的内部 ID，但不会返回给调用方，因此你无法将其与后续确认匹配。

一个 `updateId` 同一时间只能有一个待处理的运行时操作变更。发送第二个带有 `updateId` 仍在等待确认的补丁会在本地被拒绝，并在控制台显示警告；请等待第一个更新完成，或使用不同的 `updateId`.

### 读取后端确认

订阅到 `ConvaiManager.ActiveManager.Events.OnDynamicContextUpdateResultReceived` 并按 `updateId` 你发送的：

```csharp
using Convai.Domain.DomainEvents.Runtime;
using Convai.Runtime.Components;

ConvaiManager.ActiveManager.Events.OnDynamicContextUpdateResultReceived += result =>
{
    if (result.UpdateId != "lever-unlock-01")
        return;

    if (result.Status == "success")
    {
        Debug.Log($"操作已确认：objects={result.ObjectsCount}, attention={result.CurrentAttentionObject}");
    }
    else
    {
        Debug.LogWarning($"操作补丁失败：{result.Status}");
    }
};
```

`DynamicContextUpdateResultReceived` 除了一般动态上下文字段外，还携带该操作更新的类型化元数据：

| 属性                                                | 类型        | 含义                                    |
| ------------------------------------------------- | --------- | ------------------------------------- |
| `UpdateId`                                        | `string`  | 你提供的 ID `ConvaiDynamicContextUpdate`. |
| `Status`                                          | `string`  | `"success"` 在补丁应用时；其他任何值都表示它被拒绝。      |
| `ActionConfigUpdated`                             | `bool?`   | 此确认是否包含操作配置更改。                        |
| `ActionConfigCreated`                             | `bool?`   | 后端是否为该会话创建了新的操作配置。                    |
| `ActionsCount`, `ObjectsCount`, `CharactersCount` | `int?`    | 补丁后已确认配置中的最终计数。                       |
| `当前注意对象`                                          | `string`  | 补丁后的最终注意对象。                           |
| `CurrentAttentionObjectCleared`                   | `bool?`   | 此更新是否清除了注意目标。                         |
| `ActionGenerationStrategyChanged`                 | `bool?`   | 后端的操作生成策略是否更改。                        |
| `ActionGenerationStrategyStatus`                  | `string`  | 策略更改的状态字符串，包括 `"requires_reconnect"`. |
| `RawExtras`                                       | `JObject` | 仍未作为类型化属性公开的字段的后端原始载荷。                |

当 `ActionGenerationStrategyStatus` 为 `"requires_reconnect"`，SDK 会公开该状态，但不会自动重新连接——如果新策略需要，请你自己重新连接会话。

要在代码中发送补丁前预览其预测结果，请使用中描述的 Action Debug 窗口中的运行时补丁组合器 [排查角色动作问题](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/debugging-and-troubleshooting.md).

### 故障排除

#### 补丁在发送前被拒绝

**症状：** 控制台警告会指出字段名称，例如 `action_config 操作 '...' 没有本地可执行定义` 或 `重复的操作目标名称 '...'`.

**原因：** 补丁已在本地验证并失败——某个操作名称没有匹配的本地 `ConvaiActionDefinition`、某个目标名称为空或重复，或者当前注意对象无法与补丁中的对象对应。

**解决方法：** 更正警告中提到的字段，并使用新的 `updateId`.

**验证：** 控制台不会显示拒绝警告，并且 `OnDynamicContextUpdateResultReceived` 随后会为同一个 `updateId`.

#### 从未收到任何确认

**症状：** `OnDynamicContextUpdateResultReceived` 从不会为你发送的 `updateId` 你发送的，并且 `ConvaiCharacter.ActionConfig` 从未反映该补丁。

**原因：** 该更新因 30 秒确认超时、ACK 错误或错误/不匹配的确认元数据而被丢弃——控制台会记录 `运行时操作变更已丢弃 update_id=<id> reason=<reasonCode>` 在这些情况下。Convai 响应前会话断开也会丢弃该更新，但不会有任何控制台消息，且是静默的。被丢弃的更新不会自动重试。

**解决方法：** 使用新的重新发送补丁 `updateId` 一旦角色已确认连接（`IsInConversation` 为 `true`).

**验证：** `OnDynamicContextUpdateResultReceived` 触发时带有 `Status == "success"` 适用于新的 `updateId`.

### 下一步

{% content-ref url="/pages/5b02ee57da9de48585f7ea92aa9e94714547d80a" %}
[动作目标解析的工作方式](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/attention-and-reference-grounding.md)
{% endcontent-ref %}

{% content-ref url="/pages/1398e3302b345ef93934a0e6c93b4d8e576ab00e" %}
[排查角色动作问题](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/character-actions/debugging-and-troubleshooting.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/update-actions-at-runtime.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.
