> 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/dynamic-context/dynamic-context-usage-examples.md).

# 动态上下文使用示例

以下示例从单状态 Inspector 设置逐步过渡到多状态脚本场景。每个示例都包括场景背景、具体设置和预期的运行时结果。

{% hint style="info" %}
所有示例都假设 `ConvaiManager` 已在场景中，配置了有效的 API 密钥，并且目标 NPC 具有一个 `ConvaiCharacter` 已分配角色 ID 的组件，并且能够进行对话。
{% endhint %}

### 安全演练：站点跟踪

**上下文：** 一次消防抑制认证演练。一名训练员 NPC 引导操作员穿过各个抑制站。角色必须始终知道操作员当前所在的站点，以便给出针对站点的指示和危险警告。

#### 设置（Inspector）

1. 添加 `ConvaiDynamicContextCommand` 到训练员 NPC 的 GameObject 上。
2. 设置 **命令类型** 到 **设置状态**.
3. 设置 **状态名称** 到 `Station`.
4. 设置 **状态值** 到 `消防抑制区`.
5. 设置 **反应模式** 到 **立即响应** ——角色应识别每次站点切换。
6. 在消防抑制区区域添加一个触发器碰撞体。将其 `OnTriggerEnter` 事件连接到该命令的 `Execute()` 方法。

对每个额外站点，使用单独的子 GameObject 命令重复此操作，每个都使用相应的 **状态值**。在每个子命令的 **目标** 部分，禁用 **自动解析角色** 并为 NPC 的 `ConvaiCharacter` 显式分配——自动解析只会搜索同一个 GameObject。

#### 预期结果

当操作员进入消防抑制区时， `Execute()` 触发。角色接收到更新后的 `Station` 状态并立即回应：

> *“你已到达消防抑制区。鉴于当前极高的危险等级，在接触任何设备之前，请确认你已穿戴好 PPE。”*

该 `Station` 状态会保留在跟踪器中。如果操作员在任何时候问“我在哪儿？”，角色都会用当前站点值作答。

### 入职引导：批量状态更新

**上下文：** 一场企业入职模拟。HR 代表 NPC 会根据新员工已收集的物品和已通过的检查点来调整其引导。当两个条件同时满足时——应将它们作为一次原子更新发送。

#### 设置（脚本）

```csharp
using System.Collections.Generic;
using Convai.Runtime.Components;
using Convai.Runtime.DynamicContext;
using UnityEngine;

public class OnboardingProgressTracker : MonoBehaviour
{
    [SerializeField] private ConvaiCharacter _hrCharacter;

    public void OnAccessCardAndBriefingComplete()
    {
        // 批量更新——一次规范重建，一次网络往返
        _hrCharacter.DynamicContext.SetStates(
            new Dictionary<string, string>
            {
                { "AccessCard", "Collected" },
                { "SecurityBriefing", "Completed" }
            },
            ConvaiContextReactionMode.ReactImmediately
        );
    }

    public void CheckIfReadyForFloorAccess()
    {
        // 读取本地跟踪器——无需网络调用
        bool hasCard = _hrCharacter.DynamicContext.TryGetStateValue("AccessCard", out string cardState)
                       && cardState == "Collected";
        bool hasBriefing = _hrCharacter.DynamicContext.TryGetStateValue("SecurityBriefing", out string briefingState)
                           && briefingState == "Completed";

        if (hasCard && hasBriefing)
            Debug.Log("员工已准备好获得楼层访问权限。");
    }
}
```

#### 预期结果

`OnAccessCardAndBriefingComplete()` 会发送一次原子更新。HR 角色会立即回应：

> *“你已领取访问卡并完成安全简报——你已获准进入楼层。下一步请前往 4B 工位。”*

`TryGetStateValue` 会从本地跟踪器读取，不进行网络往返。如果该状态已设置，则返回当前值；否则返回 `false` 如果它从未被设置或已被移除，则返回。

### 导览游：多个命令和时间线事件

**上下文：** 一次博物馆导览游。一名讲解员 NPC 跟踪当前正在展示的展品，并按时间顺序记录访客交互。讲解员利用这些历史信息提供个性化推荐。

#### 设置（Inspector — 多个子命令）

因为 `ConvaiDynamicContextCommand` 每个 GameObject 只能有一个实例，每个命令都位于 NPC 的一个子 GameObject 上。

**子 GameObject 1 —— “SetActiveExhibit”**

* 命令类型： `设置状态`
* 状态名称： `ActiveExhibit`
* 状态值： `古罗马馆藏`
* 反应模式： `仅同步` ——展品名称静默更新；导览叙事负责节奏控制
* 目标 → 自动解析角色：已禁用；角色字段：NPC 的 `ConvaiCharacter`

**子 GameObject 2 —— “RecordVisitorQuestion”**

* 命令类型： `添加事件`
* 事件文本： `访客询问了有关斗兽场重建的问题`
* 反应模式： `Auto`
* 目标 → 自动解析角色：已禁用；角色字段：NPC 的 `ConvaiCharacter`

**子 GameObject 3 —— “RecordPhotoTaken”**

* 命令类型： `添加事件`
* 事件文本： `访客为角斗士展品拍了照`
* 反应模式： `Auto`
* 目标 → 自动解析角色：已禁用；角色字段：NPC 的 `ConvaiCharacter`

将每个子命令的 `Execute()` 连接到时间线标记、交互区域或 UI 按钮。将 **执行后** 事件连接到每个子项，以驱动 UI 反馈——突出显示展品卡片、更新导览进度——无需额外脚本。

#### 预期结果

随着访客的推进，讲解员的规范上下文会累积：

```
ActiveExhibit 为 Ancient Rome Collection
访客询问了有关斗兽场重建的问题
访客为角斗士展品拍了照
```

讲解员会同时参考当前展品和访客的具体互动：

> *“既然你拍摄了角斗士展品，也许你会喜欢下一间房间里新增的罗马军事装备展区。”*

### 紧急响应：多状态切换

**上下文：** 一次工业安全模拟。主管 NPC 必须对从常规检查到紧急模式的同时切换做出响应——三个条件同时变化，角色必须立即识别全部变化。

#### 设置（脚本）

```csharp
using System.Collections.Generic;
using Convai.Runtime.Components;
using Convai.Runtime.DynamicContext;
using UnityEngine;

public class EmergencyResponseController : MonoBehaviour
{
    [SerializeField] private ConvaiCharacter _supervisorCharacter;

    public void TriggerChemicalLeak()
    {
        // 三个状态同时变化——一次原子更新，一次规范重建
        _supervisorCharacter.DynamicContext.SetStates(
            new Dictionary<string, string>
            {
                { "OperationMode", "Emergency" },
                { "HazardType", "Chemical Leak — Bay 7" },
                { "EvacuationStatus", "In Progress" }
            },
            ConvaiContextReactionMode.ReactImmediately
        );

        // 在状态批处理之后记录触发事件
        _supervisorCharacter.DynamicContext.AddEvent(
            "7号舱位触发化学泄漏警报——已启动自动通风",
            ConvaiContextReactionMode.SyncOnly
        );
    }
}
```

#### 预期结果

主管角色接收到三个状态更新和一个事件。 `立即响应` 模式下的 `SetStates` 会触发一次立即响应，确认所有同时变化：

> *“7号舱位发生化学泄漏——所有人员立即撤离东翼。7号舱位通风已启动。在发出解除警报前，不得重新进入。”*

使用 `SetStates` 来处理三个同时发生的切换，只会生成一次规范重建，而不是三次顺序重建，从而确保角色接收到的是一致的整体信息，而不是三次部分更新。

### 下一步

{% content-ref url="/pages/5c3f9bcc544ac6f441fe54139ac1c670eeb5c958" %}
[动态上下文脚本 API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/dynamic-context-scripting-api.md)
{% endcontent-ref %}

{% content-ref url="/pages/bb1aef3496a2be08987c770aa7b8072e7d8c5cd6" %}
[同步行为和时序](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/sync-behavior-and-timing.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:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/dynamic-context/dynamic-context-usage-examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
