智能对象概述

智能对象是关卡中可以通过保留系统使用的一组活动。

Choose your operating system:

Windows

macOS

Linux

概述

智能对象(Smart Object) 是可以放置在关卡中,并且与AI代理和玩家交互的对象。这些对象包含交互所需的所有信息。

智能对象隶属于一个全局数据库,并使用一种空间分区结构。这意味着,在运行时可以通过筛选条件(例如位置、距离代理的位置、标签等)来查询它们。

总体来说,智能对象表示关卡中的一组活动,并且该活动可以通过保留系统使用。 值得注意的是,智能对象不包含执行逻辑。相反,智能对象向交互对象提供所有必要信息,以便执行交互,具体取决于其实现方法。每个交互对象(代理或玩家)都会针对智能对象自己实现逻辑。

智能对象元素

SmartObject子系统

SmartObject子系统 负责跟踪关卡中所有可用的智能对象。它是智能对象组件和集合之间的链接。当智能对象插件激活时,此子系统会在关卡中自动创建,如果缺少智能对象集合,则会创建集合。

SmartObject集合

SmartObject集合(SmartObject collection) 包含一组与关卡相关的所有SmartObject组件。该集合保存所有共享配置,并用于创建智能对象的所有运行时实例,以便在加载区域之外实现高效的大型世界模拟。

每个关卡只有一个智能对象集合。

SmartObject组件

你可以将 SmartObject组件 添加到 Actor,以便将其转换为关卡中的智能对象。该组件将设置并存储给定智能对象模板的配置。

运行时可以使用 世界分区(World Partition)流送(Streaming) 加载和卸载包含SmartObject组件的Actor。如果SmartObject组件是持久世界的一部分,则运行时实例将在内存中保持激活,并被视为模拟的一部分。如果包含SmartObject组件的Actor在运行时生成,则一旦卸载,它将不会在内存中保持激活。

智能对象定义

智能对象定义(Smart Object Definition) 是一种数据结构,它包含不可变数据,这些不可变数据会在SmartObject运行时实例的多个实例之间共享。智能对象定义保存着筛选信息,例如用户需要的标签、描述性标签和在交互时执行的默认行为集。

智能对象定义将公开一个或多个可用插槽,代理或玩家可以将插槽用于特定智能对象。每个插槽包括相对于父锚点的位置和旋转(从编辑器位置烘焙),以及几个可覆盖属性。可覆盖属性的常见示例包括用户需要的标签和每个插槽的专有行为。

智能对象行为定义

智能对象行为定义(Smart Object Behaviors Definitions) 包含代理或玩家在进行指定交互时所需的数据。一些常见的行为包括 Gameplay行为玩家行为MassEntity行为。Gameplay行为可以直接在蓝图中实现。

运行时流程

在本小节中,你将了解代理如何与关卡中的智能对象交互。

代理数据

为了搜索智能对象,代理需要有一个或多个用户标签,以及对象标签列表。在关卡中搜索匹配的智能对象时将使用此信息。

智能对象数据

智能对象包含一个或多个用于描述对象的 对象标签(object tag)。智能对象还包含用户标签列表和标签查询。标签查询是用于确定是否允许请求使用智能对象的用户与其交互的表达式。

智能对象具有 行为类(Behavior Class),其中包含用户与智能对象交互后将使用的行为定义。

搜索智能对象

  1. 代理以指定的时间间隔搜索附近的智能对象。代理通过调用智能对象子系统中的 FindSmartObjects 方法来执行搜索。该方法包含用户标签、对象标签、行为类和搜索区域。

  2. 智能对象子系统将在搜索区域内查找与对象标签匹配的全部智能对象。

  3. 每个智能对象将使用用户标签运行其标签查询,查看是否存在匹配,并将结果发送到智能对象子系统。

  4. 智能对象子系统会将智能对象结果返回给代理。智能对象结果是结构体数组,包含所有匹配的智能对象ID及其空闲插槽。

    带有两个空闲插槽的智能对象

    在上图中,你可以看到带有两个自由插槽(用灰色环表示)的长凳智能对象。

认领智能对象

  1. 代理将选择所需的智能对象结果,并调用智能对象子系统中的ClaimSmartObject方法。此方法将尝试从智能对象中认领可用插槽。

  2. 智能对象子系统将尝试从智能对象中认领可用插槽。

  3. 在智能对象中认领可用插槽,其状态设置为 已认领(Claimed) 。确认将发送到智能对象子系统。

  4. 智能对象子系统会向代理返回 认领句柄(Claim Handle)

  5. 代理会检查认领句柄是否有效。如果有效且认领尝试成功,则可以继续下一步。但是,如果认领句柄无效,代理可能会尝试从智能对象结果中认领另一个智能对象。

    被认领的插槽无法被其他代理再认领,除非被占用它的代理释放。

    带有两个已认领插槽的智能对象

    在上图中,代理在向已认领的插槽找去时,会逐渐接近工作台智能对象。

接近智能对象

  1. 代理将调用智能对象子系统中的 GetSlotLocationGetSlotTransform 方法,并传递认领句柄。此方法将返回已认领插槽的位置或变换。

  2. 智能对象子系统会将已认领插槽的位置或变换返回给代理。

  3. 代理现在可以开始寻找关卡中的插槽位置。代理可以使用所需的任意导航方法到达其目的地。

  4. 代理到达插槽位置,调用智能对象子系统中的 UseSlot 方法,并传递认领句柄。

  5. 智能对象子系统会将 行为定义(Behavior Definition) 结构体返回给代理。行为定义包含代理在插槽位置执行其所需行为的所有必要数据。

  6. UseSlot方法将触发已认领插槽的状态更改。插槽的状态从 已认领(Claimed) 更改为 已占用(Occupied)

    具有已占用插槽和已认领插槽的智能对象

    在上图中,代理到达插槽并开始执行所需的行为。插槽现在已被占用,由红色环表示。

释放智能对象

  1. 代理将执行行为定义中描述的所需行为。

  2. 行为完成或中止后,代理将使用智能对象子系统中的认领句柄调用 ReleaseSmartObject 方法。

  3. 智能对象子系统将插槽状态从 已占用(Occupied) 更改为 空闲(Free)

  4. 代理现在可以自由执行另一行为,或搜索另一个智能对象。

    代理负责释放它们已认领的插槽。它们的行为一旦完成或中断,就会发生这种情况。

中止过程

上述过程可以随时被代理或智能对象中断或中止。

如果智能对象的状态发生变化,它将自动释放所有已认领或已占用的插槽,并通过 OnSlotInvalidatedDelegate 回调通知相应的代理。常见的示例是智能对象在Gameplay期间被销毁。

代理也可以随时因故中止该过程。在这种情况下,代理负责释放插槽,以便其他代理可以认领它。常见的示例包括代理消亡,或执行优先级更高的任务。