Combining Meshes at Runtime for NavMesh Generation

Hey all,
For the current project I’m working on, I need to generate a navmesh for navigation of a city landscape. I’ve got the navmesh set up to generate at runtime but I’m having an issue due to one of my outside libraries. I’m using Mapbox to generate meshes and it creates two meshes, one for the buildings and one for the underlying map, like this:
The underlying map
alt text
The buildings layered on top
alt text
The objects are structured so that there’s a parent gameobject with one child, the map, and the map has one child, the buildings.

The main issue I’m trying to solve is that when I generate the navmesh, it runs under the buildings and my navmesh agents can’t route around them.

Things I’ve tried:

  • Marking the buildings as Navmesh obstacles. The obstacle bounding boxes were too large and so navigating through alleys was impossible

  • Apply Navmesh Modifier Volume to the buildings

  • Combining the meshes

When I try to combine the meshes, I get some very strange behavior where only the rooftops are visible, like this:
alt text

I’m not too worried about the material but I am confused as to why my buildings are missing walls.

The meshes are combined with a couple of code snippets, the first is a script that gets attached to the buildings when they are generated by mapbox. All it does is call a meshcombiner object on the building’s parent(The map tile):

MeshCombiner mc = GameObject.FindGameObjectWithTag( "MeshCombiner" ).GetComponent<MeshCombiner>();
        mc.ApplyToMapTile( gameObject.transform.parent.gameObject );

And the ApplyToMapTile function looks like this:

public void ApplyToMapTile( GameObject tile ){
        CombineInstance[] meshes = new CombineInstance[3];
     
        // grab tile mesh
        MeshFilter tmf = tile.GetComponent<MeshFilter>();
     
        meshes[0].mesh = tmf.mesh;
        meshes[0].transform = tmf.transform.localToWorldMatrix;

        // grab building mesh
        MeshFilter[] bmf = tile.GetComponentsInChildren<MeshFilter>( true );

        meshes[1].mesh = bmf[0].mesh;
        meshes[1].transform = bmf[0].transform.localToWorldMatrix;
        meshes[2].mesh = bmf[1].mesh;
        meshes[2].transform = bmf[1].transform.localToWorldMatrix;

        // Then deactive the building
        foreach( Transform child in tile.transform ){
            if( child.gameObject.name == "building" ){
                child.gameObject.SetActive( false );
            }
        }

        meshHolder = new Mesh();
        meshHolder.CombineMeshes( meshes, true );
        tile.GetComponent<MeshFilter>().mesh = meshHolder;

Where meshHolder is just some storage in the class.

All of the code is available in the Github repo

So, I have two main questions

  1. Is combining the meshes before generating the navmesh a reasonable solution to original navmesh problem ( The navmesh going under buildings and making it unusable ) ? Is there a better solution?
  2. What am I doing wrong combining the meshes to end up with just the rooftops?

Thanks all

I’ve got two ideas that might be easier than what you are doing:

  1. Generate the map mesh with holes where the buildings are located.

  2. Add a flat plane to the bottom of the building mesh