Agent stuck on 'cursed' NavMesh position generating 0 corner paths

I have a NavMesh created from a Terrain plus NavMeshObstacles. The player character contains an Agent which uses CalculatePath to run along the NavMesh to wherever you click your mouse. But there are some spots on the navmesh that seem to be “sticky” - intermittently, if the player stops there, they’re stuck there forever.

Here the player is surrounded by almost totally flat terrain in the middle of a Navmesh poly:

But from this position, a call to NavMesh.CalculatePath() from agent.transform.position to any point on the navmesh returns a path with 0 corners. Code:

NavMeshPath path = new NavMeshPath();
NavMesh.CalculatePath(agent.transform.position, validSampledNavmeshPosition, NavMesh.AllAreas, path);
if (path.corners.Length == 0) Debug.Log("Zero Corners");

Agent.isOnNavMesh is true. I can reload the game and place the agent at that exact position again to reliably recreate the issue. 95% of my NavMesh regions never cause this problem, but there are specific ‘cursed’ areas where the mesh often traps poor souls who pass through it. Video: https://bit.ly/3i7RCNP

Any thoughts? I guess I’ll teleport the player nearby if I detect a 0-corners path, but I feel like I’m sticking a bandaid over a bigger problem I don’t really understand.

What is the result of your call to NavMesh.CalculatePath()? It returns a bool indicating if the path is reachable.

One possibility in my mind is that the agent does not know it’s correct position, so debugging the agents position and confirming the location of the agent might be beneficial to figuring out the problem.

Yes NavMesh.CalculatePath() does also return false, it seems to believe the point on the mesh where the character is standing and the point on the mesh right beside them are in different universes or something.

I’m setting the agent to this position using Agent.Warp() which I think would throw an error or fail if it was an invalid position somehow. If the agent is moving freely I can also set its position via transform.position in the inspector to recreate the bug. The problem only occurs on very specific places on the mesh.

I call NavMesh.SamplePosition on the destination point before CalculatePath, so even points outside the mesh or which are blocked by NavMeshObstacles produce valid paths from the agent to the closest valid point on the navmesh. So, the destination points are valid and can be pathed to from elsewhere on the mesh.

I’ve verified I don’t have multiple navmeshes in here. I really don’t know what could be causing it…

Seems this person also ran into the same issue: NavMeshAgent getting stuck on a random point - Questions & Answers - Unity Discussions

I suggest trying their fix and reporting this bug to unity using the issue tracker. Definitely a crappy bug to run into.

Let me know if that temporary fix works though!

1 Like

Doesn’t look like a bug but just how it works in it’s own fashion. Please do report a bug if you think it really is one as there isn’t a case I know of for this, so if you share more about the problem and more about the navmesh itself it may help. It looks to me there are gaps in the navmesh as well.

A lot of people’s problems come from physics vs agent movement or a bad navmesh generated or not querying what the navmesh’s state is.

Note there are a lot of behaviours that navigation considers not a bug, but users would consider a bug. If you navigate too close to where you’re standing, it may not even return a valid path but early out.

To decipher all this you’ll need to offer much more info about the problems, the intention etc. Also check out the docs there’s a ton of info in there. Are you using built in or the package workflow?

1 Like

I hadn’t run across that unity answers issue in my searching, but it looks like their solution (toggling agent.enabled false then true) does not work for me.

Like that OP I used GitHub - Unity-Technologies/NavMeshComponents: High Level API Components for Runtime NavMesh Building and NavMeshModifierVolumes to generate my meshes. I’d forgotten that package was experimental, so it shouldn’t surprise me if it is generating buggy navmeshes. The package moved to NavMesh Building Components | AI Navigation | 1.0.0-exp.4 a few months ago so I’ll try to upgrade and report the bug if it is still happening.

While I’m upgrading, does anyone have a better suggestion for how I should generate my meshes? I have a Terrain with 4 textures. I want the player to walk along the ‘cobbled road’ texture, but not the ‘rocky hillside’ texture. Currently I have a pre-bake step where I automatically place a grid of ‘Not Walkable’ NavMeshModifierVolumes wherever the ‘rocky hillside’ texture appears. After the bake I remove them. Is there a better way? A way that doesn’t require experimental packages?

While narrowing this bug down to report, I discovered it isn’t caused by experimental classes, but seems to be a problem with NavMeshObstacles. This one in particular makes a sticky ‘dead zone’ around where the cylinder is standing, which an agent can path through and stop in but then can’t path out of. If I disable the obstacle or just turn off Carve, the agent can move freely away from this spot. Happens with a new vanilla Unity project, a Terrain mesh, and a box obstacle.

I’ve reported the bug (in issue tracker) but may have to roll my own dynamic obstacle system to work around this.

Edit: I also found a better NavMesh generation method from this post: create a copy of the navmesh and position it 0.05 units above the first. Add a NavMeshModifier to it with Override Not Walkable. Then sculpt-lower the terrain where you want the path to be, revealing the original walkable terrain underneath. Bake the mesh, disable the Not Walkable terrain. It’s hacky and horrible to maintain but bakes faster and gives much smoother navmesh edges than my grid system.

Hopefully last update - my final solution was to write a util to detect cursed regions (places on the navmesh where no path can be calculated from) then strategically place impassable rocks nearby to break them up. Bake > check for cursed points > add a rock > repeat. Different combinations of dynamic obstacles triggered different cursed areas.

It’s a hack, but works well enough combined with a backup system to warp agents out of a cursed position should they find themselves in one. Hopefully Unity will fix the underlying bug one day.

3 Likes

Sorry perhaps not reading the issue fully, but are you updating your obstacles after the removal? In my case I don’t use meshes but colliders to bake the overall navmesh so I might get different results.

Also after removing them you could try a Warp which forces the agent to update.

Can you explain what you mean by “updating your obstacles after the removal”?

Doesn’t matter if/when I warp the player Agent. The bug persists when there is no Agent in the scene at all. It even happens in edit mode.

The bug is simply: calling

NavMesh.CalculatePath(cursedSpotOnNavmesh, anyOtherPointOnNavmesh, NavMesh.AllAreas,
new NavMeshPath());

returns false when it should return true. Enabling / disabling NavMeshObstacles (set to carve the navmesh) far away on the other side of the map changes this behavior, and all the cursed spots disappear if I remove all obstacles from the scene.