This page provides some details on using multiple simultaneous Databases in a single World.
You should only need to use multiple Databases if you have multiple different types of characters that have either:
Significantly different physical proportions, such as their width or height. These physical proportions are used during the generation of the static NavData in order to determine which areas of the terrain are valid for the character to stand. For example, a narrow hallway or a low-ceilinged room might be walkable terrain for a human character but not for a giant.
Significantly different movement capabilities. These are used during the generation of the static NavData to determine whether a character can move from one place to another. For example, the generation process takes into account a maximum slope angle (set by the GenerationParameters::m_slopeMax value) that determines how steep a slope a character can traverse in its normal walking movement. For example, a mountainside might be easy for a giant spider or a mountain goat to traverse, but impossible for a human.
In cases like these, the differences in the areas of the terrain that are navigable to the two types of characters are different enough that two sets of NavData are warranted, which implies the use of two Databases to manage the different sets of NavData in the game at runtime.
Typically, the static NavData that you pre-generate for your terrain is the largest consumer of runtime memory when using Autodesk Navigation. Therefore, to avoid unnecessary duplication, you will probably want to make your characters share the same NavData whenever they can: i.e. whenever the differences between the characters are small enough that they do not cause noticeably strange behavior at runtime.
If you choose to share a single Database for multiple different types of characters, it is safest to generate the data using the radius and height of the largest character. This is readily apparent if you consider the case of the human and the giant:
In cases like this, there is a tradeoff between on one hand conserving runtime memory by sharing NavData, and on the other hand increasing path finding and path following realism by tailoring each character's NavData to their precise dimensions. Ultimately it is up to you to decide which you should prioritize in your game.
Setting up multiple Databases in a World is conceptually the same as setting up a single Database, except that you have to do everything multiple times:
The only real difference is the added challenge for your asset pipeline to ensure that you add the NavData for each type of character to the correct Database.
The Database has a mechanism for guaranteeing the coherence of its data set and preventing you from loading in any NavData generated for a different character. Once a Database has loaded any NavData, it will not load any additional NavData unless that additional NavData was generated with the same set of configuration parameters as the existing NavData.
Before you add a NavData object to a Database, you can test whether or not its data matches the data already present by calling Database::IsCompatibleWith() and passing your NavData object. If this method returns false, attempting to add that NavData to that Database will fail.
By default, whenever you add a new WorldElement such as a Bot or an obstacle to a World, that object is spatialized into all Databases in the World. This ensures that the new object is taken into account in the same way by all of the Databases. For example:
However, in some cases, you might not want this default behavior. Instead, you might want to restrict the Databases that your new objects are applied to. For example:
Each time you create a Bot, BoxObstacle, CylinderObstacle, TagVolume or PointOfInterest, you can specify which Databases should take the new object into account.
The configuration object that you use to initialize each of these kinds of objects has an m_databaseBinding member, which maintains an instance of the DatabaseBinding class. Before you initialize your object, you can create a new DatabaseBinding, set it up with pointers to the chosen Databases, and set the m_databaseBinding member to point to your DatabaseBinding. For example:
Kaim::BotInitConfig botInitConfig; ... m_databaseBinding = *KY_NEW Kaim::DatabaseBinding; m_databaseBinding->AddDataBase(world->GetDatabase(0)); m_databaseBinding->AddDataBase(world->GetDatabase(2)); botInitConfig.m_databaseBinding = m_databaseBinding; m_navBot->Init(botInitConfig);