Smart Objects Overview

Smart Objects represent a set of activities in the level that can be used through a reservation system.

Choose your operating system:

Windows

macOS

Linux

Overview

Smart Objects are objects placed in a level that AI Agents and Players can interact with. These objects contain all the information needed for those interactions.

Smart Objects are part of a global database and use a spatial partitioning structure. This means that they can be queried at runtime by using filters such as location, proximity to the Agent, and tags.

At a high level, Smart Objects represent a set of activities in the level that can be used through a reservation system. It's important to note that Smart Objects do not contain execution logic. Instead, they provide all necessary information to the interactor to be able to perform the interaction, depending on its implementation. Each interactor (Agent or Player) does its own implementation logic for a Smart Object.

Smart Object Elements

SmartObject Subsystem

The SmartObject subsystem is responsible for keeping track of all Smart Objects available in the level. This is the link between the Smart Object components and the collection. This subsystem is automatically created in the level when the Smart Objects plugin is active, and will create the Smart Object collection if it's missing.

SmartObject Collection

The SmartObject collection contains a list of all SmartObject components associated with the level. The collection holds all shared configurations and is used to create all runtime instances of Smart Objects to enable efficient large world simulation outside of loaded areas.

There is only one Smart Object collection per level.

SmartObject Component

The SmartObject component can be added to any Actor to convert it to a Smart Object in the level. The component sets up and stores the configuration of a given Smart Object template.

The Actor containing the SmartObject component may be loaded and unloaded at runtime using World Partition or Streaming. If the SmartObject component is part of the persistent world, a runtime instance will remain active in memory and will be considered as part of the simulation. If the Actor containing the SmartObject component is spawned at runtime, then it will not remain active in memory once it's unloaded.

Smart Object Definition

A Smart Object Definition is a data structure that contains the immutable data shared between multiple instances of the total number of runtime instances of a SmartObject. A Smart Object Definition stores filtering information such as user-required tags, descriptive tags, and the default set of behaviors to execute on interaction.

A Smart Object Definition exposes one or more available Slots that can be used by Agents or Players for the specific Smart Object. Each Slot includes the location and rotation relative to the parent anchor (baked from editor placement), as well as several overridable properties. Common examples of overridable properties include user-required tags and specific behavior per Slot.

Smart Object Behaviors Definition

Smart Object Behaviors Definitions contain the data needed by the Agent or Player for a given interaction. Some common behavior examples include Gameplay Behavior, Player Behavior, and MassEntity Behavior. The Gameplay Behaviors can be implemented directly in Blueprints.

Runtime Flow

In this section you will learn how Agents interact with a Smart Object in the level.

Agent Data

In order to search for Smart Objects, the Agent needs to have one or more user tags, and a list of object tags. This information will be used when searching for matching Smart Objects in the level.

Smart Object Data

Smart Objects contain one or more object tags that are used to describe the object. They also contain a list of user tags, and a tag query. The tag query is an expression used to determine if the user requesting the use of the Smart Object is allowed to interact with it.

Smart Objects have a Behavior Class which contains the Behavior Definition that will be used by the user once they are interacting with the Smart Object.

Searching for a Smart Object

  1. The Agent searches for nearby Smart Objects on a specified interval. The Agent performs the search by calling the FindSmartObjects method in the Smart Object subsystem. This method contains the user tags, object tags, Behavior Class, and search area.

  2. The Smart Object subsystem finds all Smart Objects within the search area that match the object tags.

  3. Each Smart Object runs its tag query using the user tags to see if there is a match and sends the results to the Smart Object subsystem.

  4. The Smart Object subsystem returns the Smart Object Results to the Agent. The Smart Object Results are a Struct array containing all matching Smart Object IDs and their free Slots.

    Smart Object with two free Slots

    In the image above you can see a bench Smart Object with two free Slots, denoted by the gray-colored rings.

Claiming the Smart Object

  1. The Agent selects a desired Smart Object Result and calls the ClaimSmartObject method in the Smart Object subsystem. This method will attempt to claim an available Slot from the Smart Object.

  2. The Smart Object subsystem attempts to claim an available Slot from the Smart Object.

  3. An available Slot is claimed in the Smart Object and its state is set to Claimed. Confirmation is sent to the Smart Object subsystem.

  4. Smart Object subsystem returns a Claim Handle to the Agent.

  5. The Agent checks if the Claim Handle is valid. If it is valid, the claim attempt was successful and it can proceed to the next step. However, if the Claim Handle is invalid, the Agent may attempt to claim another Smart Object from the Smart Object Results.

    The claimed Slot may not be claimed by another Agent until it is released by the current Agent occupying the Slot.

    Smart Object with two claimed Slots

    In the image above, the Agent approaches the bench Smart Object as it navigates toward the claimed Slot.

Approaching the Smart Object

  1. The Agent calls the GetSlotLocation or GetSlotTransform method in the Smart Object subsystem and passes the Claim Handle. This method returns the location or transform of the claimed Slot.

  2. The Smart Object subsystem returns the location or transform of the claimed Slot to the Agent.

  3. The Agent can now start navigating to the Slot location in the Level. The Agent can use any desired navigation method to reach its destination.

  4. The Agent arrives at the Slot location and calls the UseSlot method in the Smart Object subsystem and passes the Claim Handle.

  5. The Smart Object subsystem returns the Behavior Definition struct to the Agent. The Behavior Definition contains all the required data for the Agent to perform its desired behavior at the Slot location.

  6. The UseSlot method triggers a state change for the claimed Slot. The Slot's state is changed from Claimed to Occupied.

    Smart Object with an Occupied Slot and a Claimed Slot

    In the image above, the Agent arrives at the Slot and begins performing its desired behavior. The Slot is now Occupied, denoted by the red-color ring.

Releasing the Smart Object

  1. The Agent performs the desired behavior described in the Behavior Definition.

  2. Once the behavior is completed or aborted, the Agent calls the ReleaseSmartObject method with the Claim Handle in the Smart Object subsystem.

  3. The Smart Object Subsystem changes the Slot state from Occupied to Free.

  4. The Agent is now free to perform another behavior or search for another Smart Object.

    Agents are responsible for releasing their claimed Slots. This can happen once their behavior is completed or interrupted.

Aborting the Process

The process described above can be interrupted or aborted by the Agent or the Smart Object at any time.

If the Smart Object's state changes it will automatically release all Claimed or Occupied Slots and will notify the corresponding Agents through the OnSlotInvalidatedDelegate callback. A common example is the Smart Object being destroyed during gameplay.

The Agent can also abort the process at any time for any reason. In this scenario, the Agent is responsible for releasing the Slot so other Agents can claim it. Common examples include the Agent dying or performing another task with a higher priority.