> 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-unreal-engine-plugin/features/gaze-attention/how-gaze-attention-works.md).

# 注视注意力的工作方式

视线注意是一个位于 `UConvaiPlayerComponent` 它将玩家正在看的位置转换为 AI 角色的上下文焦点。启用后，它会在每个 tick 运行，通过高亮 Actor 和光标小部件管理视觉反馈，并在可配置的停留时间后写入聊天机器人的“注意对象”槽位。

如果你还没有启用视线注意，请先从 [视线注意快速入门](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/gaze-attention/gaze-attention-quick-start.md)开始。此页面解释该设置背后的心智模型。

### 三个核心概念

在每 tick 流程之前，请记住这三个阶段：

| 阶段        | 发生了什么                                                                          | 玩家看到什么                                    |
| --------- | ------------------------------------------------------------------------------ | ----------------------------------------- |
| **视线检测**  | 一条射线检测（以及可选的角度回退）会找到一个可被注视的 `UConvaiObjectComponent` 位于准星下方。                   | 高亮和光标会立即激活。                               |
| **停留晋升**  | 在……之后 `GazeAttentionDelay` 在同一目标上停留若干秒后，该对象会被提升为“注意中”。                         | 没有新的视觉变化； `OnAttentionGained` 会触发。        |
| **注意所有权** | 每个聊天机器人都会通过……跟踪是谁设置了它的注意槽位 `AttentionSource`。视线只有在该槽位为 `无` 或者已经归视线所有时，才能更新该槽位。 | 角色可能会说话，也可能保持沉默，这取决于 `GazeShouldRespond`. |

带标签的对象来自场景元数据——请参阅 [场景元数据如何工作](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/scene-metadata/how-scene-metadata-works.md)。注意所有权与代词指代锚定与 [注意与指代锚定](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/character-actions/attention-and-reference-grounding.md).

### Tick 流程

每个 tick， `UConvaiPlayerComponent` 调用 `TickGazeAttention` 当 `bEnableGazeAttention` 为 `true`。下图展示完整的决策路径；后面的编号列表将详细说明每个阶段。

```mermaid
flowchart TD
    A([TickGazeAttention]) --> B{bEnableGazeAttention？}
    B -- 否 --> Z([跳过])
    B -- 是 --> C[沿 GazeTraceChannel 进行射线检测\n最远到 GazeMaxDistance]
    C --> F[GatherMatchingObjects]
    F --> D{有效的视线目标？}
    D -- 是 --> I[生成 / 更新\nAConvaiGazeHighlightActor]
    D -- 否 --> E{AngleTolerance > 0\n且主射线未被\n非 Convai 几何体阻挡？}
    E -- 是 --> G[点积回退：\n遍历子系统池]
    E -- 否 --> H([本 tick 没有视线目标])
    G --> Q{回退目标？}
    Q -- 是 --> I
    Q -- 否 --> H
    I --> J[更新 UConvaiGazeCursorWidget\n状态：Active 或 Idle]
    J --> K[Tick GazeAccumulator\n或 NoGazeAccumulator]
    K --> L{GazeAccumulator >=\nGazeAttentionDelay？}
    L -- 是 --> M([PromoteToAttention\n触发 OnAttentionGained])
    L -- 否 --> N{NoGazeAccumulator >=\nGazeAttentionLossDelay？}
    N -- 是 --> O([ReleaseAttention\n触发 OnAttentionLost])
    N -- 否 --> P([累积——无状态变化])
```

1. 一条射线从玩家摄像机或 VR HMD 向前发射，沿着 `GazeTraceChannel` （默认 `ECC_Visibility`）最远到 `GazeMaxDistance` （默认 5000 厘米）。
2. 会检查射线结果是否命中一个可被注视的 `UConvaiObjectComponent` 在命中的 Actor 上。只有当对象是整体 Actor 范围，或者命中的原语与对象配置的组件范围相匹配时，才会接受该视线目标。
3. 如果严格的射线检测没有命中有效的视线目标，则会在以下情况下运行点积回退： `GazeAngleTolerance` 大于零，且主射线未被非 Convai 几何体阻挡。该回退会遍历所有 `UConvaiObjectComponent` 已在子系统中注册的对象，丢弃任何超出范围、位于相机后方或超出锥体半角的对象，并选择与视线方向点积最高的那个。这样可避免球形射线的物理查询，并且行为与距离无关——远处对象所需的屏幕容差与近处对象相同。
4. 任何视线目标之间的切换（进入或离开）都会触发 `OnGazeBegin` 或 `OnGazeEnd` 在玩家组件上，并更新光标小部件状态。
5. 两个累加器并行运行： `GazeAccumulator` 统计当前目标已被持续注视了多久，而 `NoGazeAccumulator` 统计玩家已经离开任何 Convai 对象多久。

### 注意晋升与释放

当 `GazeAccumulator` 达到 `GazeAttentionDelay` 秒（默认 1.0）后，视线目标会被提升为“注意中”：

* 玩家组件会调用聊天机器人组件上的内部方法，并传入 `FConvaiObjectEntry` 目标的……以及 `GazeAttentionText` 和 `GazeShouldRespond`。这一切都会自动处理——无需 Blueprint 连线。
* `OnAttentionGained` 会在玩家组件上触发。
* 聊天机器人的 `AttentionSource` 属性会被标记为 `EConvaiAttentionSource::Gaze`.

当 `NoGazeAccumulator` 达到 `GazeAttentionLossDelay` 秒（默认 5.0）后，且玩家不再注视当前注意 Actor/原语组合时，槽位将被释放：

* 玩家组件会调用聊天机器人组件上的内部方法来清空注意槽位。同样，这也是自动完成的。
* `OnAttentionLost` 会在玩家组件上触发。
* 聊天机器人的 `AttentionSource` 重置为 `EConvaiAttentionSource::None`.

### 注意来源锁定规则

聊天机器人通过……跟踪最后一次设置其注意槽位的是谁 `AttentionSource` (`EConvaiAttentionSource`）。该 `AttentionSource` 上的属性 `UConvaiChatbotComponent` 会经历三个状态：

```mermaid
stateDiagram-v2
    [*] --> None
    None --> Gaze : TrySetObjectInAttentionFromGaze()
    Gaze --> Gaze : 新的视线目标被晋升
    Gaze --> None : TryClearObjectInAttentionFromGaze()\n或丢失计时器到期
    None --> Explicit : 从 Blueprint/C++ 调用 SetObjectInAttention()
    Gaze --> Explicit : 从 Blueprint/C++ 调用 SetObjectInAttention()
    Explicit --> None : 使用空的 FConvaiObjectEntry 调用 SetObjectInAttention()
    Explicit --> Explicit : 使用新对象调用 SetObjectInAttention()
```

| 值                   | 含义                                      |
| ------------------- | --------------------------------------- |
| `无`                 | 注意槽位为空。                                 |
| `视线`                | 槽位最后由视线系统设置。                            |
| `显式（Blueprint/C++）` | 槽位最后由一次直接的 `SetObjectInAttention` 调用设置。 |

基于视线的更新只有在……时才会成功 `AttentionSource` 为 `无` 或 `视线`。直接调用 `SetObjectInAttention` 从 Blueprint 或 C++ 调用会将 `AttentionSource` 到 `显式`，并锁定该槽位。槽位被锁定时，视线调用会被静默拒绝。要释放显式锁定，请调用 `SetObjectInAttention` 并使用空的 `FConvaiObjectEntry`.

{% hint style="warning" %}
如果某个角色的注意槽位无论玩家看向哪里都始终停留在同一个对象上，请检查是否有某个 Blueprint 图正在调用 `SetObjectInAttention` 并且从未清空它。该 `AttentionSource` 聊天机器人上的只读属性会显示当前由哪个系统拥有该槽位。
{% endhint %}

### 注意与动作系统

`SetObjectInAttention` 在……时没有效果 `启用动作` (`bEnableActions`）为 `false` 在聊天机器人上启用时。只有当 `action_config` 块在会话连接时被包含——而这要求已启用动作。因此，视线注意要求聊天机器人上的动作系统处于激活状态。

### 组件范围的视线

默认情况下，Actor 上的每个 `UConvaiObjectComponent` 都代表整个 Actor——视线系统会高亮所有网格，并将该 Actor 作为一个整体进行晋升。要将视线范围限定到某个子网格，请设置 `ObjectEntry.MoveTargetMode` 到 **以组件为目标** (`Vector`）并将 `ObjectEntry.ComponentName` 设置为目标组件名称中不区分大小写的子字符串。使用默认的 **以 Actor 为目标** 模式时，非空的 `ComponentName` 不会影响视线。

`GatherMatchingObjects` 将 `UConvaiObjectComponent` 命中 Actor 上的实例分为两组：

| 组        | 条件                                                              | 触发条件：                                                                                      |
| -------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| 整体 Actor | `MoveTargetMode` 为 `以 Actor 为目标`，或 `ComponentName` 为空           | 当 Actor 没有已解析的组件范围对象时，命中该 Actor 的任意碰撞都会触发。如果同一 Actor 上的某个组件范围对象匹配，则整体 Actor 对象会作为“搭载”一并触发。 |
| 组件范围     | `MoveTargetMode` 为 `以组件为目标` 和 `ComponentName` 解析到该 Actor 上的某个网格 | 命中的碰撞基元与已解析组件匹配（或附着于其上）                                                                    |

当某个组件范围组件匹配时，同一 Actor 上的任何整体 Actor 组件也会触发（“搭载”规则）。如果该 Actor 已解析出组件范围对象，但命中的碰撞基元与它们都不匹配，则该次命中不会触发任何视线对象。

**示例——一个带有两个 Convai 对象的门 Actor：**

```
BP_Door
├── ConvaiObjectComponent "Door"        → MoveTargetMode: 以 Actor 为目标
└── ConvaiObjectComponent "DoorHandle"  → MoveTargetMode: 以组件为目标, ComponentName: "Handle"
    └── 目标是该 Actor 上的 SM_Handle
```

* 玩家看向门框 → 不会触发任何视线对象，因为该 Actor 具有已解析的组件范围对象，而命中的碰撞基元与之不匹配。
* 玩家看向把手 → `ConvaiObjectComponent "DoorHandle"` 触发； `ConvaiObjectComponent "Door"` 也会触发（搭载）。高亮 Actor 仅限定到 `SM_Handle` 仅此一个。

`ComponentName` 匹配为不区分大小写的子字符串查找，解析一次后会缓存。调用 `GetResolvedComponent(true)` 如果组件树在运行时发生变化，可强制刷新。未解析的 `ComponentName` 会在首次组件解析时记录警告，并且该组件会被排除在范围限定的视线流程之外。

{% hint style="info" %}
使用组件范围的 `UConvaiObjectComponent` 实例，让一个复杂道具暴露多个独立交互点——每个都有自己的 `名称`, `描述`、以及视线事件——而无需复制父 Actor。
{% endhint %}

### 视觉反馈

#### 高亮 Actor

当识别出一个视线目标时， `UConvaiPlayerComponent` 会生成（或复用）一个 `AConvaiGazeHighlightActor` 覆盖在目标之上。高亮 Actor 使用 `UMeshComponent::SetOverlayMaterial` 在 UE 5.3 及更高版本中为目标网格着色。默认情况下，高亮 Actor 会加载 `/ConvAI/Highlights/M_ConvaiGazeOverlay`，这是插件源代码引用的一个 Fresnel 边缘轮廓材质。该 Actor 会将 `GazeHighlightColor` 写入材质的 `EmissiveColor` 和 `Color` 向量参数，然后将 `GazeHighlightEmissiveIntensity` 写入 `EmissiveIntensity` 标量参数。

在 UE 5.0–5.2 中， `SetOverlayMaterial` 不适用于 `UMeshComponent`。该 Actor 会回退为使用一个 `DrawDebugBox` 线框围绕目标边界框，并使用 `FallbackBoxThickness` 和 `FallbackBoxPadding`.

当某个组件范围的 `UConvaiObjectComponent` 匹配时，高亮会限定到该特定子网格，而不是 Actor 上的每个网格。请参阅 [组件范围的视线](#component-scoped-gaze) 上文中的匹配规则。

#### 光标小部件

一个 `UConvaiGazeCursorWidget` 在以下情况下，当视线跟踪处于激活状态时，它会被添加到视口中： `bShowGazeCursor` 为 `true`。该小部件有两种视觉状态：

* **空闲** ——视线未落在任何 Convai 对象上。使用 `GazeCursorIdleColor` （默认 alpha 为 0，完全透明）绘制。
* **激活** ——视线落在某个 Convai 对象上。使用 `GazeCursorActiveColor` （默认白色）绘制。

状态之间的过渡会在……期间进行插值 `GazeCursorFadeInTime` 和 `GazeCursorFadeOutTime`。当 `bAlwaysShowGazeCursor` 为 `true`时，即使视线没有落在 Convai 对象上，光标也会保持在“激活”视觉状态。

该光标是一个纯 C++ 小部件，使用 Unreal 的 `FCoreStyle::WhiteBrush`。插件不附带任何纹理资源。要显示自定义准星，请在 Blueprint 中继承 `UConvaiGazeCursorWidget` ，重写 `OnGazeStateChanged`，并将该子类分配给 `GazeCursorWidgetClass` 在玩家组件上。

### 下一步

{% content-ref url="/pages/c5d49eeda517161a96ea3016fa123bc1694b506f" %}
[视线注意快速入门](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/gaze-attention/gaze-attention-quick-start.md)
{% endcontent-ref %}

{% content-ref url="/pages/797ae18ef94bcef2ec7816f079c7a35fb212a26c" %}
[视线注意力参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/gaze-attention/gaze-attention-reference.md)
{% endcontent-ref %}

{% content-ref url="/pages/2f301cf695f654f0b6dc66672ff9462854021237" %}
[注视注意力使用示例](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/gaze-attention/gaze-attention-usage-examples.md)
{% endcontent-ref %}

{% content-ref url="/pages/ca4f4235151ab1fee69bb58487611f1c6ec30cc6" %}
[排查注视注意力问题](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/gaze-attention/troubleshoot-gaze-attention.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-unreal-engine-plugin/features/gaze-attention/how-gaze-attention-works.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.
