Before reading this guide you might want to watch the detailed overview video (at least the first 5-10 minutes) too.
Also keep the sample project handy, comparing your setup with the sample project is the easiest way to verify or troubleshoot your setup.
1. Preparing your project
“Finite World” Navigation:
The finite manager is much faster than the “Infinte Worlds” manager (see below) but restricts navigation activity to a fixed, specific volume. It also uses much more memory in comparison and for dynamic maps it requires you to trigger dynamic obstacle updates yourself. Use this for small worlds with static obstacles or rarely changing collision geometry.
- For Finite Worlds place “DonNavigationManager” Actor into your map
- Use it to set the size of the navigable world, voxel density, performance settings as desired.
- Add the collision channels that need to be treated as obstacles in the Obstacle Query Channels list. By default it includes WorldStatic and WorldDynamic.
- This actor is also the API entry point for calling blueprint nodes and C++ functions.
“Infinite Worlds” Navigation:
The infinite/unbound manager can be used anywhere, anytime with absolutely no limits, even in fully procedural worlds with collision geometry changing every second. It is very slow compared to the Finite World manager but in a packaged game (Shipping build with no debug information) it should be sufficient for most games. Use this for large worlds or procedural games with highly dynamic, ever-changing collision geometry.
- For Infinite Worlds place “DonNavigationManagerUnbound” Actor into your map
- Set the voxel size to your liking. You do not need to set the X, Y, Z grid sizes though, they are ignored in the infintie navigation mode.
- If you need faster pathfinding or if you find that your pathfinding requests are timing out you can increase the “MaxSolverIterationsPerTick” variable. Very high values may affect your FPS, so bear that in mind. Again, packaged/shipping builds will perform much faster.
2a) Performing Navigation via Behavior Trees
“Fly To” behavior tree node accompanies this plugin for people who’re using Behavior Trees.
- Drop the Fly To behavior tree node into your tree.
- Set the FlightLocationKey dropdown to a blackboard key that represents your pawn’s desired Flight Location.
- If you’re unsure of Step 2, please refer to Unreal Engine’s Behavior Tree documentation on how to use behavior trees and create tasks as that is well outside the scope of this document. You can also study the sample project’s behavior trees which include fully working examples of Patrolling (flying to a desired goal and back) and Pursuit (A.I. chasing a player around the map).
- Once you have added the Fly To node the plugin will guide your pawn along the “Path Solution” by calling your pawn’s AddMovementInput function and passing in a direction vector representing the world direction your pawn needs to move.
- You need to implement whatever flying movement/locomotion your bot needs for it travel to the goal. To achieve this, Implement AddMovementInput (provided by UnrealEngine, also has a default implementation for Pawn/Character classes) or AddMovementInput_Custom (a custom interface provided by this plugin named IDonNavigator) to guide your bot along the direction passed to you. The plugin will find the shortest path to a destination of your choice and then allows you to guide your bot along that path by implementing any aerial locomotion of your choice.
2b) Performing Navigation via the API
Advanced users can invoke the Navigation API directly from either Blueprints or from C++. To perform pathfinding use the function SchedulePathfindingTask available in the navigation managers. Many other functions are also available in the API and fully documented.
3) Scheduling Dynamic Collision Updates
If your map is highly dynamic or procedural or has frequently moving obstacles that your A.I. needs to circumvent, you should use the API to call ScheduleDynamicCollisionUpdate whenever your obstacles move or change in any other way. This will tell the Navigation Manager to resample the collision geometry of that obstacle and updates the navigation graph used for pathfinding. This step is currently not necessary for the Infinite/Unbound manager, which is fully dynamic by default.
4) Gotchas and Common Issues
Q) My pawn doesn’t do anything with the “Fly to” node?
A) First check the logs. I make extensive use of logs to report common issues and potential solutions. The most common reasons are:
- Your origin or destination is colliding with world geometry. This is not permitted. If your character has an extra mesh that is tagged WorldStatic or WorldDynamic (just an example) it will be treated as an obstacle and the nav query aborts.
- Your origin or destination is colliding with the floor. Moving these up a bit should help.
- You’re trying to navigate to a point outside the navigable world. You may need to increase the values of XGridSize or YGridSize or ZGridSize as necessary.
- Your trigger volumes have an object type of WorldStatic or WorldDynamic (which is default Unreal behavior) and may be overlapping with origin or destination. This won’t work for the plugin as the system relies on overlaps instead of sweeps for performance so all trigger volumes should use a unique object type. See the sample project’s green button trigger volumes for an example.
- Your pawn hasn’t implemented AddMovementInput. This is what the FlyTo node calls to make your pawns move. Characters and most pawns should already have it (except the APawn baseclass itself), but if it doesn’t, you need to implement it. BP users can implement my interface AddMovementInputCustom as they don’t have access to override the pawn’s AddMovementInput routine.
Q) The log says my pathfinding queries are timing out?
A) Sometimes a query will time-out because it is too complex and exceeds the time-out limit (you can customize the time-out limit and other parameters under “Query Params”). Other times a query will time out because it has no solution and so the path-finder is scanning through potentially millions of voxels (this is not an exaggeration – large maps with high accuracy (low voxel sizes) can easily reach 4 to 6 million voxels!) in the wrong direction searching in vain for a goal. Again – if a pawn is too close to the floor and if your character is big then it will “get stuck”. If your voxelsize is high (i.e. low accuracy) then you always need to leave sufficient head room from the floor for all queries.
Q) My pawn is bumping into obstacles!?
A) Unfortunately this does happen at times. There are usually workarounds to most situations though. Try increasing the “max optimizer sweep attempts” parameter, or decrease voxel size for more accuracy or increase the frequency of your dynamic collision update checks.
There’s more, but these are all I can think of for now!