注视注意力如何工作
了解注视追踪管线、注意力提升计时器、组件范围目标、高亮渲染以及注意力源锁定规则。
视线注意是一个位于 UConvaiPlayerComponent 它将玩家正在看的位置转换为 AI 角色的上下文焦点。启用后,它会在每个 tick 运行,通过高亮 Actor 和光标小部件管理视觉反馈,并在可配置的停留时间后写入聊天机器人的“注意对象”槽位。
如果你还没有启用视线注意,请先从 视线注意快速入门开始。此页面解释该设置背后的心智模型。
三个核心概念
在每 tick 流程之前,请记住这三个阶段:
视线检测
一条射线检测(以及可选的角度回退)会找到一个可被注视的 UConvaiObjectComponent 位于准星下方。
高亮和光标会立即激活。
停留晋升
在……之后 GazeAttentionDelay 在同一目标上停留若干秒后,该对象会被提升为“注意中”。
没有新的视觉变化; OnAttentionGained 会触发。
注意所有权
每个聊天机器人都会通过……跟踪是谁设置了它的注意槽位 AttentionSource。视线只有在该槽位为 无 或者已经归视线所有时,才能更新该槽位。
角色可能会说话,也可能保持沉默,这取决于 GazeShouldRespond.
Tick 流程
每个 tick, UConvaiPlayerComponent 调用 TickGazeAttention 当 bEnableGazeAttention 为 true。下图展示完整的决策路径;后面的编号列表将详细说明每个阶段。
一条射线从玩家摄像机或 VR HMD 向前发射,沿着
GazeTraceChannel(默认ECC_Visibility)最远到GazeMaxDistance(默认 5000 厘米)。会检查射线结果是否命中一个可被注视的
UConvaiObjectComponent在命中的 Actor 上。只有当对象是整体 Actor 范围,或者命中的原语与对象配置的组件范围相匹配时,才会接受该视线目标。如果严格的射线检测没有命中有效的视线目标,则会在以下情况下运行点积回退:
GazeAngleTolerance大于零,且主射线未被非 Convai 几何体阻挡。该回退会遍历所有UConvaiObjectComponent已在子系统中注册的对象,丢弃任何超出范围、位于相机后方或超出锥体半角的对象,并选择与视线方向点积最高的那个。这样可避免球形射线的物理查询,并且行为与距离无关——远处对象所需的屏幕容差与近处对象相同。任何视线目标之间的切换(进入或离开)都会触发
OnGazeBegin或OnGazeEnd在玩家组件上,并更新光标小部件状态。两个累加器并行运行:
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 会经历三个状态:
无
注意槽位为空。
视线
槽位最后由视线系统设置。
显式(Blueprint/C++)
槽位最后由一次直接的 SetObjectInAttention 调用设置。
基于视线的更新只有在……时才会成功 AttentionSource 为 无 或 视线。直接调用 SetObjectInAttention 从 Blueprint 或 C++ 调用会将 AttentionSource 到 显式,并锁定该槽位。槽位被锁定时,视线调用会被静默拒绝。要释放显式锁定,请调用 SetObjectInAttention 并使用空的 FConvaiObjectEntry.
如果某个角色的注意槽位无论玩家看向哪里都始终停留在同一个对象上,请检查是否有某个 Blueprint 图正在调用 SetObjectInAttention 并且从未清空它。该 AttentionSource 聊天机器人上的只读属性会显示当前由哪个系统拥有该槽位。
注意与动作系统
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:
玩家看向门框 → 不会触发任何视线对象,因为该 Actor 具有已解析的组件范围对象,而命中的碰撞基元与之不匹配。
玩家看向把手 →
ConvaiObjectComponent "DoorHandle"触发;ConvaiObjectComponent "Door"也会触发(搭载)。高亮 Actor 仅限定到SM_Handle仅此一个。
ComponentName 匹配为不区分大小写的子字符串查找,解析一次后会缓存。调用 GetResolvedComponent(true) 如果组件树在运行时发生变化,可强制刷新。未解析的 ComponentName 会在首次组件解析时记录警告,并且该组件会被排除在范围限定的视线流程之外。
使用组件范围的 UConvaiObjectComponent 实例,让一个复杂道具暴露多个独立交互点——每个都有自己的 名称, 描述、以及视线事件——而无需复制父 Actor。
视觉反馈
高亮 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 上的每个网格。请参阅 组件范围的视线 上文中的匹配规则。
光标小部件
一个 UConvaiGazeCursorWidget 在以下情况下,当视线跟踪处于激活状态时,它会被添加到视口中: bShowGazeCursor 为 true。该小部件有两种视觉状态:
空闲 ——视线未落在任何 Convai 对象上。使用
GazeCursorIdleColor(默认 alpha 为 0,完全透明)绘制。激活 ——视线落在某个 Convai 对象上。使用
GazeCursorActiveColor(默认白色)绘制。
状态之间的过渡会在……期间进行插值 GazeCursorFadeInTime 和 GazeCursorFadeOutTime。当 bAlwaysShowGazeCursor 为 true时,即使视线没有落在 Convai 对象上,光标也会保持在“激活”视觉状态。
该光标是一个纯 C++ 小部件,使用 Unreal 的 FCoreStyle::WhiteBrush。插件不附带任何纹理资源。要显示自定义准星,请在 Blueprint 中继承 UConvaiGazeCursorWidget ,重写 OnGazeStateChanged,并将该子类分配给 GazeCursorWidgetClass 在玩家组件上。
下一步
注视注意力快速入门注视注意力参考注视注意力使用示例排查注视注意力问题最后更新于
这有帮助吗?