Right so, I’m working on this properly now and after studying UT’s source code in ridiculous detail, I think I’ve found a way to do this (based on a similar method).
The idea is to create additional data and store it in the RecastNavMesh Actor. This data essentially clusters polygons of the navmesh together, first based on whether or not NavAgents of the same size can traverse each polygon, then based on whether or not each polygon of a cluster can reach another cluster. You then create ‘Path Nodes’ (as UT calls them, probably a throwback to UDK) - and store that path link data there.
I have an early version working in terms of the NavMesh generation, but I will have to alter the way valid paths are actually generated from NavMesh in order for the AI to start using them. I tried doing this with NavLinks first, but Links are a bit rubbish to be honest, and aren’t useful for connecting ‘area’s’, so much as specific world locations. It’s also ridiculously difficult to place these dynamically, so any kind of procedural or moving level stuff won’t work with it.
This is where I’m at so far:
Essentially you generate the NavMesh first, then add an additional loop for constructing your own data once the Mesh has been generated. I haven’t yet figured out how to force-rebuild the paths when only moving a segment of the world, so at the moment I have to manually hit ‘Build Paths’ in the editor to generate the paths properly for the whole level.
void AECGame_RecastNavMesh::OnNavMeshGenerationFinished()
{
// If a path build is in progress, do nothing
if (bPathsAreRebuilding) { return; }
if (bPathsNeedRebuilding)
{
// Once Polygon building has completed, start building the paths
StartPathBuild();
}
else
{
// Polys and Paths should have finished building, we can clean up now.
Super::OnNavMeshGenerationFinished();
}
}
Then, you select an island in the Navmesh, and create a Path Node for it. Each PathNode knows which Nav Polygons it’s responsible for (NavNodeRef). If a polygon in that island can be traversed by a same sized agent as the other polygon, then you link them to that node. The idea is to have as few nodes as possible, since later for pathfinding you’ll need to iterate nodes to generate the cheapest paths.
This is the islands linked to each other. I used Debug Arcs to show the linked polygons because it’s easier to see what’s going on.
Recast generates NavMesh inside world geometry, so you need to filter out those islands from the traversable islands by testing for collision. I just do an overlap test with a 1UU sphere at that Polygons world location, which seems to be a good enough test for now. There are islands inside the geometry, which only link to themselves and not other nodes. In future I want to stop generating nodes inside geometry at all really…
I still have a few steps to go, but I think this is the right route:
1 - Link together nodes that can be ‘jumped’ to from other nodes, or ‘sprint-jumped’ to for extra distance. This part is a bit more complicated, since you need to check the Jump Arc for collisions.
2 - Allow NavArea’s to affect Node / Link generation to give me some way to block off some areas entirely (or change the traversal type)
3 - Figure out a way to make the AI pathing choose routes using the Path Node data.
4 - Ensure the AI tells the pawn to ‘Jump’ and ‘Crouch’, based on the path it’s traversing.
UT does quite a few things I don’t want to do, like it’s own custom pathing and using AI state machines instead of BT’s - so the path generation side of things will probably be quite challenging…