Recast Graph Rasterization Creates Incorrect Holes

I’m troubleshooting pathfinding behavior and I notice that large meshes do not consistently cut correct holes in generated pathfinding. The center of this tree is not traversable and the mesh collider is a convex collider. I do not believe this should happen.

I can adjust edge simplification but doing so has other consequences.

Perhaps this is related to ( Terrain Cut-Out Sizing Issue w/ Mesh vs Cyllinder Colliders - #8 by stonstad ), where it is noted that MeshColliders seem to be creating cuts without consistent application of the character radius.

Above

Below

Admin note: The suggestion is here:

Add a RecastNavmeshModifier set to “Unwalkable Surface” for Surface Type, and Solid to true :+1:

Thanks for the response, tealtxgr. Why do I need to add a RecastNavMeshModifier for every terrain tree? This doesn’t seem right.

If you want a technical reason I can ping Aron on this to answer?

If you want an alternative, I’d just recommend letting the holes exist. Units can’t pathfind to them on account of the gap, and if you need to get a random point on the surface, these islands can be filtered out using methods like PathUtilities.IsPathPossible.

I appreciate your helpful guidance! The issue I have with this behavior is that it seems like a bug to me. Trees are obstructions that should be flagged as unwalkable surfaces by default. My game’s procedural worlds have thousands of trees and I am bothered by the wasted computational overhead associated with this bug or behavior.

I’d 1000% at least give it a shot before assuming it’ll not be performant. The scan happens anyways after all on the object, and maybe adding a MonoBehavior to each object could loose performance. But it’s hard to know what that’d look like without trying it and comparing before and after in the Profiler. Moreover this math would only happen on scan as far as I’m aware, and if you have an open world you’re likely also using Procedural Graph Follower, which means every thousands of objects aren’t being scanned in the first place.

Or, tis my speculation.

If you’re looking for a solution requiring no MonoBehaviors, you can edit line 256 of VoxelRasterization.cs from:

if (mesh.solid) {
	for (int z = meshBounds.ymin; z <= meshBounds.ymax; z++) {
		for (int x = meshBounds.xmin; x <= meshBounds.xmax; x++) {
			voxelArea.ResolveSolid(z*voxelArea.width + x, m, voxelWalkableClimb);
		}
	}
}

to

if (true) {
    for (int z = meshBounds.ymin; z <= meshBounds.ymax; z++) {
       for (int x = meshBounds.xmin; x <= meshBounds.xmax; x++) {
          voxelArea.ResolveSolid(z*voxelArea.width + x, m, voxelWalkableClimb);
       }
    }
}

(or just take out the if statement altogether) to force solid on ALL scanned objects. I tested this out on a single cube for brevity and it worked as expected. Two caveats: I do not know how this would affect your game in your situation specifically or if there are meshes that you need not solid, and you’d also have to change this line every time you readd the package or if this file is updated.

I wouldn’t classify this a bug- this is, so the old saying goes, working as intended. It’s just working as the inverse of what you may expect. I can retag this post as suggestion for Aron to inverse the solid/non-solid workflow by defaulting if you’d want? Then we can get his words directly on a) if he has any easier options for this, b) if he thinks reversing that bool is the right call (there very well may a bigger performance issue reversing that bool than adding a MonoBehavior to all objects, I wouldn’t know!).

The modification to source looks like a great approach! Thank you!

1 Like

Hi @tealtxgr

I tried out the source modification approach and while it does make terrain system trees non-walkable, it prevents the inside of my buildings from being walkable.

There needs to be a way to instruct the voxelization process to treat trees as solid obstacles. While this may not be a bug, it is a limitation that limits usability. Trees should by obstacles by default, or at minimum, configurable as non-walkable.

I can’t instantiate monobehaviors to every tree because that would require the addition of thousands of scripts to all the trees with in a grid area. For the overall map, we are talking about 100,000+ trees/scripts.

Are you able to give us a profiler before and after of using RecastNavmeshModifier? I understand that’s not your ideal fix but if we can start with some actual numbers we can likely optimize this route to actually work for you.

I will still tag this as a suggestion (with a note on the OP) for having the PerLayerModification struct contain a solid option as well.

and the mesh collider is a convex collider

All convex mesh colliders should be treated as solid by default. Can you verify that you are using an up to date version of the package, and that your recast graph settings include “Rasterize Colliders” and not just “Rasterize Meshes”?

Hey Aron,

  • I’m using 5.4.6 · January 22, 2026
  • Rasterize colliders is checked (see screenshot below)
  • The tree is a convex collider (see screenshot in previous post)

Hmmm. Can you see if there’s perhaps some bounding box issue. Is the tree extending above/below the graph’s bounding box?

The tree has a convex collider and appears to be in the graph’s bounds. Tree_06_3

OK, I see the cause. It’s a bad collider. I’m OK to close this. Sorry for the trouble, guys.

1 Like

@aron_granberg @tealtxgr

Hate to bring this thread back to life, but I do think there is a bug here. I fixed the collider for the above tree and this fixes the recast graph generation as expected.

However, other trees with larger radius (with valid collider meshes) manifest the behavior. NPC pathfinding tries to cross through the geometry island, sometimes.

Example:

Hi

That collider does not look convex.

It is not convex – should they just be ignored in this scenario? It looks like they are partially supported somehow.

Recast rasterizes each triangle of the collision, which is why non convex meshes are always at risk of having interior navigation islands, if there is enough space inside any given mesh collider.

Support for convex meshes is pretty unique to this project. Most recast implementations(default unity, unreal) don’t support that. Even convex mesh collision in unreal and default unity often have internal navigation islands.

For sure. Ideally, a graph would compute a reduced complexity collider (i.e. sphere collider or convex collider) for pathing purposes. The trees could then remain non-convex for player interactiojn purposes.