Using NavData at Runtime

NavData is managed in your game at runtime through the use of one or more Databases: objects that are in charge of maintaining coherent sets of NavData for characters that share the same physical dimensions and movement models.

If you have already completed the integration tutorial in this documentation (see Integrating Navigation into your Game Engine), you should be familiar with the basic uses of a Database to load and unload NavData at runtime. This page, along with the other topics in this section, provides some additional details and considerations.

Creating Databases

When you create a World, you must specify how many Databases that World should create and maintain. See Integration Phase 1c: Setting up a World.

Each Database can only load NavData that was created with the same set of configuration parameters. If you have characters whose physical dimensions or movement capabilities are different enough that they cannot share the same NavData, you will need to set up multiple Databases for your World. For details, see Using Multiple Databases.

The number of Databases maintained by the World cannot be changed after creating the World.

Loading NavData into memory

In order to add NavData for your terrain or a sector of your terrain into a Database, you must first create a NavData object, set it up with data by reading the data from a file or a memory buffer, and initialize it with the Database that will manage it.

For a code example that shows how to load from a file, see Integration Phase 3: Loading and Unloading NavData.

For a code example that shows how to load from a memory buffer, see Integration Phase 6a: Integrating NavData into your Asset Pipeline.

Adding and Removing NavData in a Database

When you want to add your NavData to a Database in order to make it available for the path finding, path following and query systems, or to remove the NavData from the Database when it is no longer needed in the game, you have a choice of two methods: immediate or asynchronous.

Immediate

This is the most straightforward way to add and remove NavData. Use the following methods of the NavData class:

KyResult NavData::AddToDatabaseImmediate();
KyResult NavData::RemoveFromDatabaseImmediate();

With this approach, a full update of the Database is immediately launched, and the calling thread is blocked until the update is complete. During this update, the new data is fully stitched into the existing NavData or fully decoupled from the rest of the NavData.

This approach has the obvious advantage of ensuring that the data that is available to your Bots and queries is always up-to-date with the latest additions or removals that you have made. However, since this approach causes the entire update to occur during the current frame, it can cause CPU peaks when used with large data sets in a real production. In addition, it requires you to be careful about multi-threading; if you are performing queries in another thread, modifying the data those queries are relying on may cause unexpected results or even crashes. It is therefore intended primarily for use during your initial integration and prototyping phases, with the expectation that you will eventually want to move to asynchronous addition and removal of data.

Note however that if you are loading your data outside of the context of a game loop, such as in a post-processing phase of your data generation process, you must use this approach.

Asynchronous

The safe way to add and remove NavData is to use the following methods:

KyResult NavData::AddToDatabaseAsync();
KyResult NavData::RemoveFromDatabaseAsync();

With this approach, the request to add or remove the NavData is registered, and is processed in subsequent frames during the update of the World.

The Database manages all of the complexities involved in tracking the data addition and removal processes. However, it may be useful for you to track the status of your requests, so that you know whether your Bots and queries are using the latest changes you have made to the set of NavData in the Database. Each NavData object maintains its own status value, accessible through NavData::m_databaseStatus, which indicates the current status of that NavData within its assigned Database.

The following image summarizes how these status values are set in response to addition and removal requests. The status values are shown in red, user-initiated actions in black, and internal actions in blue:

Unloading NavData from memory

After you have removed your NavData object from its Database, you should always set any pointers you have maintained to that NavData object to KY_NULL. This decrements the reference counting mechanism.