Navigation on map doesn’t change at runtime. All/almost all walkable areas have single Z value for given XY pair, aka no overhangs.
Custom navigation data actor holding arrays of 2D tiles, one for height data shared across all lanes, one for move directions. Directions are stored for specific lane + team pair to suit project needs.
Important overrides:
- ConditionalConstructGenerator() : custom generator
- GetBounds() : required
- NeedsRebuild() : keeping in sync with navmesh, set by NavigationSystem, cleared after flow field rebuild
- ConstructRenderingComponent() : data rendering
Also some caches, lookups, reading data from flow fields at given location, etc.
Navigation system overrides OnNavigationGenerationFinished() to mark flow field nav data as dirty when navmesh is updated. We spawn and register flow field nav data manually in Build() override, although right now I don’t remember why…
Supported agents define both navmesh and flow field actors, but only navmesh have valid agent size (radius+height), to ensure that all AIControllers are using it by default.
Path following component makes use of FCustomMoveSharedPtr param in RequestMove() to switch between using regular navigation path and flow fields. Second option is skipping everything in UpdatePathSegment() and reads desired velocity at agent location from cached flow field inside FollowPathSegment() function.
Move itself it triggered by simple behavior tree task: cache data, make FAIMoveRequest with custom game data param and send it along fake FNavigationPath to AIController.RequestMove()
Always use navmesh paths during combat.
Custom navigation data generator handles creating actual flow fields. Since we’re using navmesh to do all path findings, build have to wait for it.
Important overrides:
- RebuildAll() : try to start (NavigationSystem.GetMainNavData, check if generator is still running - IsBuildInProgress())
- TickAsyncBuild() : the same
- IsBuildInProgress() : wait until rebuild is finished
Generation itself it pretty straight forward:
- gather lane data from actor markup
- build poly graphs for each lane+team pair flooding navmesh from goal, use polys on lane axis to guide exploration (costs)
- once we have walkable space defined (sum of graphs), generate 2D tiles, locations of samples and shared data (height, etc)
- for each tile, run async task that goes through all samples in tile, finds desired move point, path to it and stores direction along first segment
- postprocess data to add some smoothing, handle drop down links
- additionally, mark all navmesh polys outside walkable space (inside geometry) with null area for easier projection later
It’s worth to mention, that running expensive part - pathfinding and postprocess - in parallel (Async, TFuture types) allowed signification speed boost for rebuild in editor (2m down to 10s IIRC). Also, navmesh exploration and building lane graphs needs to be done manually through RecastNavMesh.GetPolyNeighbors because built in flooding will very likely exceed limit of visited nodes.
(sorry for hijacking thread
)