Error during ReCast graph scan

Any thoughts on what’s causing this error? Am I doing something wrong? This is version 4.0.4, and it doesn’t seem to happen every time a scan is done. Just some times.

NullReferenceException: Object reference not set to an instance of an object
at Pathfinding.TriangleMeshNode.GetVertexInGraphSpace (Int32 i) [0x00013] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\NodeClasses\TriangleMeshNode.cs:93
at Pathfinding.NavmeshBase.CreateNodes (System.Int32[] tris, Int32 tileIndex, UInt32 graphIndex) [0x0005a] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\NavmeshBase.cs:886
at Pathfinding.RecastGraph.CreateTile (Pathfinding.Voxels.Voxelize vox, VoxelMesh mesh, Int32 x, Int32 z, Int32 threadIndex) [0x0018c] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\RecastGenerator.cs:917
at Pathfinding.RecastGraph.BuildTileMesh (Pathfinding.Voxels.Voxelize vox, Int32 x, Int32 z, Int32 threadIndex) [0x00181] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\RecastGenerator.cs:857
at Pathfinding.RecastGraph.BuildTiles (System.Collections.Generic.Queue1 tileQueue, System.Collections.Generic.List1[] meshBuckets, System.Threading.ManualResetEvent doneEvent, Int32 threadIndex) [0x000a8] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\RecastGenerator.cs:545
UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
UnityEngine.Logger:LogException(Exception, Object)
UnityEngine.Debug:LogException(Exception)
Pathfinding.RecastGraph:BuildTiles(Queue1, List1[], ManualResetEvent, Int32) (at C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\RecastGenerator.cs:547)
Pathfinding.c__AnonStorey2:<>m__0(Object) (at C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\RecastGenerator.cs:652)

(Filename: C:/Users/Jesse/Documents/repos/Unity/exile/Assets/AstarPathfindingProject/Generators/NodeClasses/TriangleMeshNode.cs Line: 93)

NullReferenceException: Object reference not set to an instance of an object
at Pathfinding.RecastGraph+c__Iterator1.MoveNext () [0x00417] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\RecastGenerator.cs:694
at Pathfinding.RecastGraph+c__Iterator0.MoveNext () [0x000c0] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Generators\RecastGenerator.cs:490
at AstarPath+c__Iterator3.MoveNext () [0x0015e] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Core\AstarPath.cs:1616
at AstarPath+c__Iterator2.MoveNext () [0x002c7] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets\AstarPathfindingProject\Core\AstarPath.cs:1562
at LoadScene+c__Iterator1.MoveNext () [0x0059b] in C:\Users\Jesse\Documents\repos\Unity\exile\Assets_Code\Network\LoadScene.cs:220
at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) [0x00028] in C:\buildslave\unity\build\Runtime\Export\Coroutines.cs:17

(Filename: C:/Users/Jesse/Documents/repos/Unity/exile/Assets/AstarPathfindingProject/Generators/RecastGenerator.cs Line: 694)

Hm… That is really odd…
I can only think of one case where it could potentially happen and that would be if you happened to start to scan a recast graph, and then while it was being scanned you would add a new graph to the AstarPath object or remove one. The code technically doesn’t catch that case right now.

Wait. After having looked over all relevant code for the last 10 minutes I think I have found a potential race case.

Open the TriangleMeshNode.cs file and find the SetNavmeshHolder method. Change the implementation from

if (_navmeshHolders.Length <= graphIndex) {
	// We need to lock and then check again to make sure
	// that this the resize operation is thread safe
	lock (lockObject) {
		if (_navmeshHolders.Length <= graphIndex) {
			var gg = new INavmeshHolder[graphIndex+1];
			for (int i = 0; i < _navmeshHolders.Length; i++) gg[i] = _navmeshHolders[i];
			_navmeshHolders = gg;
		}
	}
	_navmeshHolders[graphIndex] = graph;
}

to

// We need to lock to make sure that
// the resize operation is thread safe
lock (lockObject) {
	if (graphIndex >= _navmeshHolders.Length) {
		var gg = new INavmeshHolder[graphIndex+1];
		_navmeshHolders.CopyTo(gg, 0);
		_navmeshHolders = gg;
	}
	_navmeshHolders[graphIndex] = graph;
}

I hate multithreading bugs. They are really hard to spot.

Okay I’ll give that a shot, it’ll be a bit before I know if it’s resolved or not since it’s mostly a random error.

Yeah I understand.
I’m pretty sure that was the cause though.

The multi-threaded recast code is relatively new, so not that many people have tested it. Personally I have never seen that error, but I usually test it on relatively small worlds and it would be more likely on large worlds.

So that change completely destroyed my performance, and this profiler screenshot is of after the navmesh has already been scanned. It pretty consistently just locks up the game.

Uh huh…
That method should only contain cold code. I wouldn’t expect that lock to be contended at all.

I have no idea. If I change that back though my performance goes back to how it has been.

Strange. I will have to debug more on my end.

Have you made any progress on this?

I get the same error. I use version 4.0.11. Not sure if it helps but I never had this error until I started scanning the graph from the game instead of the unity editor.

Here is the callstack:

NullReferenceException: Object reference not set to an instance of an object
Pathfinding.TriangleMeshNode.GetVertexInGraphSpace (Int32 i) (at Assets/Standard Assets/AstarPathfindingProject/Generators/NodeClasses/TriangleMeshNode.cs:93)
Pathfinding.NavmeshBase.CreateNodes (System.Int32[] tris, Int32 tileIndex, UInt32 graphIndex) (at Assets/Standard Assets/AstarPathfindingProject/Generators/NavmeshBase.cs:894)
Pathfinding.RecastGraph.CreateTile (Pathfinding.Voxels.Voxelize vox, VoxelMesh mesh, Int32 x, Int32 z, Int32 threadIndex) (at Assets/Standard Assets/AstarPathfindingProject/Generators/RecastGenerator.cs:861)
Pathfinding.RecastGraph.BuildTileMesh (Pathfinding.Voxels.Voxelize vox, Int32 x, Int32 z, Int32 threadIndex) (at Assets/Standard Assets/AstarPathfindingProject/Generators/RecastGenerator.cs:801)
Pathfinding.RecastGraph+c__Iterator1+c__AnonStorey2.<>m__0 (Int2 tile, Int32 threadIndex) (at Assets/Standard Assets/AstarPathfindingProject/Generators/RecastGenerator.cs:600)
Pathfinding.Util.ParallelWorkQueue`1[Pathfinding.Int2].RunTask (Int32 threadIndex) (at Assets/Standard Assets/AstarPathfindingProject/Utilities/AstarParallel.cs:91)

@Isdrambo

Can you replicate that error consistently?
If so I would love to take a look at your project if you want to share it with me.

Firstly though I would suggest you to upgrade to 4.1.10 as it is very possible that the bug has already been fixed.

Unfortunately I can’t replicate it consistently. Sometimes I get this error 5 times in a row, sometimes I can’t get after 10+ attempts.

I’m about to upgrade to 4.1.10. I’ll let you know if I get this error again.

Thanks for the quick reply!

1 Like