"Smart object" is a generic term for an object that manages any kind of special interactions with your characters as they follow their paths — anything that is not managed natively by the path following system. Smart objects can take many possible forms, depending on the needs of your scenario and gameplay, the way you want to interact with your animation subsystems, etc. For example, smart objects might:
The Gameware Navigation SDK does not provide any default implementations of smart objects. Instead, it exposes all the tools that you need to write your own custom smart objects that take partial or total control over your characters' movements at specific times during the path following process.
When you write your own smart objects, the exact steps that you will have to carry out in your code depend heavily on the effect you are trying to create. However, the most typical kinds of smart objects will probably use most if not all of the strategies presented on this page.
You will probably want to use NavTags to tag the areas of your terrain that you want to be controlled by each of your smart objects. This is not absolutely necessary; you can successfully integrate your own smart objects without using NavTags. However, NavTags are integrated into the path following system, offering you an easy way to determine when your characters plan paths that include your smart objects, and when they approach the areas controlled by the objects.
The typical approach is to use NavTags to embed custom IDs that you can use at runtime to determine which type of smart object each area of NavData refers to. For instance, a NavGraph that represents a ladder could be tagged with one ID value, while a NavGraph that represents an elevator would be tagged with a different value.
How exactly you set up these NavTags in your NavData depends on the kind of object you want to create.
For information about NavTags, see Tagging with Custom Data.
For information about TagVolumes and dynamic obstacles, see Using Dynamic Obstacles and TagVolumes.
You may need your smart object to keep track of the characters that are intending to use it. You can therefore make your characters respond appropriately to changes in the state of the smart object. For instance, when a door becomes locked or a bridge gets destroyed, you may want your characters to re-compute their paths to find a different path to their goals. This usually involves registering each character with the smart object when it plans a path that includes that smart object, and un-registering it if its path changes and no longer includes the object.
To register and unregister your characters with the smart objects that lie along their paths, you can use a custom implementation of IPathEventListObserver that checks each newly created path for events that have been tagged with the NavTag associated with one of your smart objects.
For more on using an IPathEventListObserver, see Monitoring PathEvents.
As your characters follow their paths, you will need to monitor for upcoming smart objects. As your characters get close to the object, they should begin asking the smart object for instructions.
Typically, this means checking the NavTag of the next PathEvent upcoming on the character's path. You can do this by calling Bot::GetUpcomingEventNavTag(). If the NavTag returned matches the ID associated with a smart object, you can make your smart object register the character as currently traversing it, and can begin giving directions to the Bot. It may take control of the character's movements immediately, or it may allow the Bot to continue following its path normally until it gets within a certain distance.
Eventually, your smart object will probably take control over the movements of the character for a limited time while the character traverses the object: i.e. while it goes through the door, climbs the ladder, stands on the elevator, plays a particular animation, etc. When you want to take full control, you should de-activate the path following system for the character by calling both Bot::SetDoValidateCheckPoint() and Bot::SetDoComputeTrajectory(), passing false to both methods.
After your character has successfully moved through the smart object, or has finished whatever movements the smart object has determined that it needs to carry out, you can re-enable the path following system by calling both Bot::SetDoValidateCheckPoint() and Bot::SetDoComputeTrajectory() again, passing true to both methods.
Note that when you took control of path following, you disabled the target point computation. The current target point maintained by the Bot is therefore still where it was when you took control: typically, back at the path event that lies at the start of the smart object that the character just traversed. When you release control, you may therefore need to advance the target point along to the end of the smart object, in order to ensure that your character does not try to traverse the smart object again. You can do this as follows:
// Get the next NavTag along the path from the current position on the path. // Since the current position is still where it was when the smart object took // control, we know that this method will return the NavTag at the other end of the // interval of the path that is controlled by the smart object. const Kaim::NavTag* smartObjectTag = m_navBot->GetUpcomingEventNavTag(); // This class is a predicate that determines which NavTag we want to move through. Kaim::NavTagMovePositionOnPathPredicate predicate(smartObjectTag); // We retrieve the current position on the LivePath. Kaim::PositionOnLivePath positionOnLivePath = m_navBot->GetProgressOnLivePath(); // This call moves the position on the path forward until the predicate says to stop. // The NavTagMovePositionOnPathPredicate says to stop when a tag other than the // smartObjectTag is reached, which will be the PathEvent that lies at the other end // of the smart object. m_navBot->MovePositionOnPathForwardToNextEvent( positionOnLivePath, &predicate );
Depending on the nature of your smart object, you may or may not want to allow a Bot to re-calculate a new path while it is using the smart object. For example, you might want to prevent new path calculations while a Bot is jumping or vaulting in order to stop it from changing directions in mid-air, or while a Bot is using an elevator. On the other hand, you might want to allow new paths while a Bot is climbing a ladder or using a door. The typical way to handle this is for your Bot class to check with the current smart object before it computes a new path.
However, in some cases, your smart object may be linked to a NavGraph that takes the Bot too far outside the borders of the NavMesh for the path finding system to hook itself to the NavMesh. Or, you may need to force the Bot to begin its new path on a particular edge of the NavGraph. You can still re-compute a new path while the Bot is using the smart object in these cases; however, because the position of the Bot is not spatialized into the NavMesh while it is using the smart object, you must set up the AStarQuery with the NavGraph edge or vertex that you want the new path to start with.
Similarly, you can plan a path that ends in a smart object, even if that destination is not inside the NavMesh, by setting up the AStarQuery with the NavGraph edge or vertex that you want the new path to end with.
For details, see AStarQuery Options.
The LabEngine project contains examples of several different types of smart objects, including doors, elevators, ladders, lava that needs to be jumped over, etc. These smart objects are used in the SDK samples that you can launch in the Navigation Lab; see Getting Started with the Navigation Lab . The complete source code for these objects is provided for you to use as a model. See the files under the tools\LabEngine\include\LabEngine\smartobjects and tools\LabEngine\src\smartobjects directories.