Using the Apex Utility AI to Scan and Store Observations about other GameObjects

Introduction

This document is a part of a series of tutorial documents for getting started with the Apex Utility AI.

The purpose of this document is to provide a description to the classes used in the scene “AI_Demo_3”, as well as a tutorial on how to create a simple Apex Utility AI with the capability to observe other GameObjects using standard Unity functionality.

AIContext

We need to add three properties to the Context. These properties are:

  • The AI itself. we need to know which GameObject is the one observing, otherwise it might store an observation of itself.
  • A list of Observations. So the AI can keep track of what we have already observed.
  • A method to handle the adding and updating of the Observations, which can be seen in the code snippet below. This method checks if the AI has already observed the GameObject. If it has, it then updates the information about that GameObject. Otherwise it adds a new Observation to the list with information about the GameObject.

The method for adding or updating an Observation can be seen in the below code snippet. The code uses a float-based timestamp field on the Observation class, to determine whether a given Observation is newer than a previous one.

Observation

The Observation class is a wrapper for the entities that are observed. As you can see in the example code snippet below, this class is very small, it only contains a GameObject property as well as a Timestamp property. However, in a real game it would be extended with any relevant related data. The timestamp is used to determine whether we need to update the data of what we have observed. For example, if we observed a GameObject ten seconds ago, but we have an observation with a newer timestamp already, we then have “old” data, and chances are that e.g. the position of that GameObject has changed.

Tip
The idea of storing observations in a separate class is that the AI can add information about that particular observation, such as the state of the game object, e.g. health, the direction the GameObject is pointing, position of the GameObject etc. If the GameObject disappears from sight, the state at the time of observation is stored and can be used by the AI to analyze for example tactical situations or to exchange information about observations with other AIs.

EntityScanner

The EntityScanner class derives from ActionBase, and is used by the AI to scan for potential observations. In the Execute method the AI uses the Physics.OverlapSphere method to look for GameObjects on the specified Unity Layer within a radius. GameObjects are subsequently added to a list as Observations or information about an existing Observation is updated with the latest data and timestamp. Note that the AI avoids adding its own GameObject to the list. The Execute method can be seen in the code snippet below:

Tip
If you want the AI to also check for visibility, you can use a Physics.RayCast to establish whether the AI can see each of the GameObjects. If you want to check whether the GameObjects observed are in the field of vision of the AI, you can use Vector3.Angle to check against the angle of vision of the AI.

ObservationVisualizer

To make debugging easier, we make use of Apex Utility AI visualizers to visualize the observations that the AI has made. In this example we add a class that extends the CustomGizmoVisualizerComponent. This enables us to decide what we want to draw using Unity Editor Gizmos. In this example we draw lines to the GameObjects in the Observation list. Note that we pass two types to the class that we are extending: EntityScanner and ObservationContext. This is to let the AI know when to draw the gizmos (i.e. When the Apex Utility AI action ScanForEntities is being executed), as well as giving the DrawGizmos method the context type that it needs to operate.

Behaviour

On the Default Action, we add the EntityScanner Utility AI action and select what Layer we want to scan against in the settings (Unity inspector) of the EntityScanner action. Here we also choose the radius of the scanning. When we have added the newly created AI to the Utility AI Component, we have everything we need for the AI to scan. We need to add the ObservationVisualizer to an empty GameObject in the scene to use it. Finally, ensure that the GameObjects of the potential targets are in the same layer as the one chosen in the EntityScanner settings. When we run the scene and select the Unit in Unity’s scene hierarchy, we can see white lines drawn towards every GameObject that the AI has observed. In the image below, the AI has observed all three GameObjects.