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.
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!).
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.
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”?
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.
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.