Waypoints Technical Guide
Navigation is based on a pre-generated path network. As this path network doesn't cover 100% of the areas a bot may traverse, they also have to be able to perform localized assessment and navigation of the environment, which they sample for these purposes using collision traces, as well as inspection of nearby objects in the collision data structure.
Level designers should place down NavigationPoints within a map. When the level is built, the NavigationPoints will generate ReachSpecs between then which has data used by path finding which allows AI to path find from A to B.
What are anchors?
An anchor is a navigation point that the AI can directly reach, without having to perform path finding, and thus is where path searches are started from. The first step of path finding, on any sort of path graph, is to find the most appropriate start and end points on the graph in order to generate a path between them. The anchor represents the start point for the bot's path searches, such that after calling FindPathToward() you will have a route from anchor to goal.
This function is queried by an AI during a move in order to ascertain whether or not it should consider the object it is currently moving toward as 'reached'. In other words, the AI calls this to decide whether it should stop moving to the current destination, and either move on to the next object in its route or stop moving altogether because it has arrived at its overall goal. Note that this function calls ReachedBy() on the Actor the AI is trying to move to which gives custom objects a chance to have a say in when an AI should stop trying to move to it. A good example of how this is useful is on very large objects. Normally an AI would try and run to the location of the object until it is inside some radius of said object, but if it has collision which is larger than the radius its checking against obviously this would cause problems. For objects such as this you could just override ReachedBy() to take into account its custom dimensions.
The AI can call this function to decide if an object is directly reachable or not. This means that the AI can run in a straight line to the object without running into something (that it can't jump over). This is used during moves to decide a few things, but a good example is when it uses this function to decide if it should run straight to its destination, or try to path there via the path network.
It's best to view the source code for examples. That said, at a high level what this function does is as follows:
- Try and early-out by determining if the actor we're checking against is on a ReachSpec we are standing on, or if the destination actor is within the radius of a navigation point we are also within. (Assumes reachspecs / navigation points are always valid to walk along, as they are verified off-line).
- Does a quick ray cast to see if the destination is visible at all and early outs if it's not.
- Check to see if the destination actor is above solid ground.
This function will execute a traversal of the path network generating a route from the AI's position to the passed goal, placing the generated route (An ordered list of waypoints from the anchor to the goal) in the RouteCache of the controller. This will tell the AI what waypoints to move to in order to reach its goal.
FindPathToward() determines how to travel towards an actor by first ensuring that the AI's anchor is valid (and try to find a new one if it's not), and then run a traversal across the path network to generate a route from the anchor to the goal. Once this route is generated the AI will run toward the first point in the route directly, until ReachedDestination() determines it has arrived at the waypoint, which will then trigger the AI to run to the next waypoint in the generated route.
FindPathToward() just generates the route for the AI to use, so if you're seeing bots clipping or rounding corners and getting stuck as a result, something else is awry. It's best to use the console command show paths to see if lines (ReachSpecs) are going through the corner.
This is a latent function which moves the bot directly to the passed point, and finishes on arrival. This function does no path finding, it just directs the pawn straight toward the target.
This is very similar to MoveTo(), except it takes an actor as a destination and has some special handling that makes use of this extra data. (Will set anchor if the AI is moving toward a navigation point, etc.).