Download

Can I serialize the navigation mesh for a procedural level?

Ok so a bit about our setup, we have a Level Streaming layout for our game so that hex based levels are streamed into the world as tiles. Each tile(sub-level) is set to zero and moved/rotated into place, the tiles are all quite large compared to the size of our characters.

Capture2.png

Building the navigation mesh for the 3-7 tiles we spawn for each new play through can be a little lengthy, not too bad at around 5-10 secs on a dev machine, but not something I would like to have happen every time a player loads the game.
I managed to get the navigation mesh to fully compute once we generate a level for the first time using this



#ifndef WITH_EDITOR
	nav_system->SetGeometryGatheringMode( ENavDataGatheringModeConfig::Instant );
	nav_system->Build();
	nav_system->SetGeometryGatheringMode( ENavDataGatheringModeConfig::Lazy );
#endif

The with_editor flags is just so that while we are doing level design/creation we don’t need to wait on the nav mesh and can leave it in the Lazy configuration we have set on the project settings by default.
We also need it in the lazy configuration to allow the user to place down buildings/walkways etc and have the nav mesh update without blocking. We have a lot of our character interactions with the resources and such in the world use the GetRandomPointInNavigableRadius() functionality for finding somewhere to get to, and therefore cannot have the Lazy config on loading a game with characters already in the world or they will not find any navigation points available to them.
What I’m wondering is if it is possible to serialize the NavMesh to data when we create a save file and load it again for this specific level layout the player has had generated, just to reduce the load time once we have done the initial work.
Our save system is using a subclass of the



struct FSaveGameArchive : public FObjectAndNameAsStringProxyArchive

and our save functions look mostly like,



void
AGameStateVillage::Serialize( TArray<uint8>& out_ )
{
	FMemoryWriter memory_writer( out_, true );
	FSaveGameArchive data_archive( memory_writer );

	data_archive << NavMesh_somehow?;
}

This would be I would think the best way to deal with the problem although I have seen some information posted around about setting up your game to use the bFixedTilePool size and DynamicModifiersOnly, so that each sublevel we stream in would have its own navigation bounds and set of navigation data it would load (currently the persistent world just has a single Nav bounds to encapsulate the entirety). I have not been able to get any good results from this and am wondering if anyone else is doing something similar?
I have been through and looked at a lot of the Navigation System and attempted a couple of different ways to serialize the nav mesh but I haven’t managed to stumble across anything that jumps out at me and says, hey this is how the editor deals with baking and loading a nav mesh.
If anyone knows where/how this works could you point me in the right direction?