ArgumentOutOfRangeException in Line Cast API?

We’ve been encountering an out of range exception while using the RecastGraph’s line casting methods (which indirects into the NavMeshGraph’s linecasting methods; sorry if I categorized this thread incorrectly!). I’ve tried to find a reproducible test case, but it’s been very elusive and only crops up once every couple of weeks.

Here is an error log:

ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
System.Collections.Generic.List1[UnityEngine.Vector3].get_Item (Int32 index) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:311) Pathfinding.NavMeshGraph.Linecast (INavmesh graph, Vector3 tmp_origin, Vector3 tmp_end, Pathfinding.GraphNode hint, Pathfinding.GraphHitInfo& hit, System.Collections.Generic.List1 trace) (at Assets/AstarPathfindingProject/Generators/NavMeshGenerator.cs:494)
Pathfinding.RecastGraph.Linecast (Vector3 origin, Vector3 end, Pathfinding.GraphNode hint) (at Assets/AstarPathfindingProject/Generators/RecastGenerator.cs:2309)
NavMeshSample.CellsAreLinear (Int32 aIndex, Int32 bIndex) (at Assets/Scripts/Prototype/AI/NavMeshPrototype.cs:111)
LinearMoveAgent.RecursiveFurthestLinearItem (.NavMeshSample sampler, System.Collections.Generic.Dictionary2 cameFrom, .GraphItem adjacent, .GraphItem prev) (at Assets/Scripts/Prototype/AI/NavMeshPrototype.cs:364) LinearMoveAgent.RecursiveFurthestLinearItem (.NavMeshSample sampler, System.Collections.Generic.Dictionary2 cameFrom, .GraphItem adjacent, .GraphItem prev) (at Assets/Scripts/Prototype/AI/NavMeshPrototype.cs:354)
LinearMoveAgent.FurthestLinearItem (.NavMeshSample sampler, System.Collections.Generic.Dictionary`2 cameFrom, .GraphItem adjacent, .GraphItem current) (at Assets/Scripts/Prototype/AI/NavMeshPrototype.cs:341)
LinearMoveAgent+c__AnonStorey92.<>m__93 (.NavMeshSample sampler) (at Assets/Scripts/Prototype/AI/NavMeshPrototype.cs:288)
NavMeshSample+c__AnonStorey91.<>m__90 (Boolean force) (at Assets/Scripts/Prototype/AI/NavMeshPrototype.cs:146)
AstarPath.ProcessWorkItems (Boolean force) (at Assets/AstarPathfindingProject/Core/AstarPath.cs:1006)

It appears the ‘left’ array ends up with 0 elements in it despite the fact that the Linecast method depends on it being at least of length 1? I’m not sure if this entails a small logic error somewhere in GetPortal, or if we’re doing something silly I haven’t been able to detect, or what.

Anybody have insight about this?

Hi

Hm… Are you possibly running graph updates at the same time?
I wonder if that will work well since updating recast graphs can be done asynchronously…

We are indeed doing a bunch of graph slicing (often immediately before attempting to do all these linecasts!). HOWEVER, all the math I’m doing takes place within the callback of an AstarPath.active.AddWorkItem() invocation, which I had assumed would wait for the completion of any recast recalculations?

Hi

So the linecasts are also done inside a work item? If so, nothing else should be interfering.

Also, do you think you could post a small snippet of code from where the exception was thrown? The line numbers differ between different versions, so it’s hard to pinpoint the exact location by just looking at the backtrace.

The particular line at which the exception occurs is:

“Vector3 a = left[0];”

And here is some surrounding context:

left.Clear();
right.Clear();

if (!node.GetPortal (node.connections[i],left,right,false)) continue;

Vector3 a = left[0];
Vector3 b = right[0];

//i.e Right or colinear
if (!Polygon.LeftNotColinear (a,b,hit.origin)) {
	if (Polygon.LeftNotColinear (a, b, tmp_end)) {
		//Since polygons are laid out in clockwise order, the ray would intersect (if intersecting) this edge going in to the node, not going out from it
		continue;
	}
}

My problem posted “Linecast on Recast graph with Links. Exception!
Might be of the same kind, as this one. It also throws exception on line Vector3 a = left[0]

					if (!node.GetPortal(node.connections[i].node, left, right, false)) continue;

					Vector3 a = left[0];
					Vector3 b = right[0];

					//i.e Left or colinear
					if (!VectorMath.RightXZ(a, b, hit.origin)) {
						if (VectorMath.RightXZ(a, b, tmp_end)) {
							//Since polygons are laid out in clockwise order, the ray would intersect (if intersecting) this edge going in to the node, not going out from it
							continue;
						}
					}

I have added: if (left.Count == 0 || right.Count == 0) continue; inside Linecast method

  			left.Clear();
  			right.Clear();
  			if (!node.GetPortal(node.connections[i].node, left, right, false)) continue;
                //TODO this was added by me to because of bug with linecast and links
                //
                if (left.Count == 0 || right.Count == 0) continue;

Now it kind of works. The problem is i do not know if it will not break something in the future. Also modifying 3rd party code is a smelly tactics.

Also I should have mention that I connect Nodes with the simplest of Node Links.

(also answered in the other thread).

Ah. Yes that indeed looks like a bug. I couldn’t replicate it when it was originally posted, but your hint about using links made it easier to debug.

I think the issue stems from an incorrect return value in the GetPortal method. It would only happen if the two nodes were in different tiles, but were still connected while not sharing an edge.

Here is a diff of the required fix (I think).
If you find the TriangleMeshNode.GetPortal method, go to the bottom and add that ‘return true’ line and change the ‘return true’ line at the bottom of the method to ‘return false’. Let me know if this fixes the bug.