Error during ReCast graph scan


#1

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)


#2

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.


#3

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.


#4

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.


#5

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.


#6

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.


#7

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


#8

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


#9

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


#10

Have you made any progress on this?


#11

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)


#12

@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.


#13

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!