A GetNearest() function that returns null if not found on graphs (solved)

Hello Aron,
How are you? I was able to solve the question I was having. I changed the GetNearest() functions to GetNearestOnGraph() which means I had to change all the GetNearest() calls in the other c# scripts. Then I made a duplicate of the original GetNearest() functions and added an extra variable called onGridSensitivity. Setting the number to be higher means that the function can more easily detect if the point provided is on a grid or not, and if not to return a new NNInfo() through an if statement…

if (!OnGrid(position, onGridSensitivity)) { return new NNInfo(); }

at the top of the GetNearest() function code where GetNearestOnGraph() does not have that if statement.

Next, I had to write an OnGrid() function. Here is the function…

`
//Determines if the point is on any graph.
public bool OnGrid( Vector3 pos, float onGridSensitivity) {
return OnGrid(pos, onGridSensitivity, -1);
}

//Determines if the point is on any graph.
public bool OnGrid(Vector3 pos, float onGridSensitivity, int graphMask) {
           return (AstarPath.active.GetNearestDistanceToGraphs(pos) < onGridSensitivity);
}

`

The GetNearestDistanceToGraphs() function returns the distance between the point given, and the closest node on the closest graph. It is also a duplicate of GetNearest(), but instead of returning a node, it returns a float value of the minDist variable. If the distance is greater than the new variable ‘onGridSensitivity’, then the point is considered off the graphs. Here is the GetNearestDistanceToGraphs() function also in AstarPath.cs along with OnGrid() and GetNarestOnGraph()…

`
/** Returns the closest distance to a graph’s node.
* */
public float GetNearestDistanceToGraphs (Vector3 position, NNConstraint constraint, Node hint) {

	if (graphs == null) { return -1; }
	
	if (constraint == null) {
		constraint = NNConstraint.None;
	}
	
	float minDist = float.PositiveInfinity;//Math.Infinity;
	NNInfo nearestNode = new NNInfo ();
	int nearestGraph = -1;
	
	for (int i=0;i<graphs.Length;i++) {
		if (enabled[i]) { 
		NavGraph graph = graphs[i];
		
		//Check if this graph should be searched
		if (!constraint.SuitableGraph (i,graph)) {
			continue;
		}
		
		NNInfo nnInfo;
		if (fullGetNearestSearch) {
			nnInfo = graph.GetNearestForce (position, constraint);
		} else {
			nnInfo = graph.GetNearest (position, constraint);
		}
		
		Node node = nnInfo.node;
		
		if (node == null) {
			continue;
		}
		
		float dist = ((Vector3)nnInfo.clampedPosition-position).magnitude;
		
		if (prioritizeGraphs && dist < prioritizeGraphsLimit) {
			//The node is close enough, choose this graph and discard all others
			minDist = dist*(int)nnInfo.priority;
			nearestNode = nnInfo;
			nearestGraph = i;
			break;
		} else {
			if (dist*(int)nnInfo.priority < minDist) {
				minDist = dist*(int)nnInfo.priority;
				nearestNode = nnInfo;
				nearestGraph = i;
			}
		}
		}
	}
					
	//No matches found
	if (nearestGraph == -1) {
		return minDist;
	}
	
	//Check if a constrained node has already been set
	if (nearestNode.constrainedNode != null) {
		nearestNode.node = nearestNode.constrainedNode;
		nearestNode.clampedPosition = nearestNode.constClampedPosition;
	}
	
	if (!fullGetNearestSearch && nearestNode.node != null && !constraint.Suitable (nearestNode.node)) {
		
		//Otherwise, perform a check to force the graphs to check for a suitable node
		NNInfo nnInfo = graphs[nearestGraph].GetNearestForce (position, constraint);
		
		if (nnInfo.node != null) {
			nearestNode = nnInfo;
		}
	}
	
	if (!constraint.Suitable (nearestNode.node) || (constraint.constrainDistance && (nearestNode.clampedPosition - position).sqrMagnitude > maxNearestNodeDistanceSqr)) {
		return new float();
	}
	
	return minDist;
}`

To know what graphs to enable and disable in order to get around the problem I had earlier of the seeker not being able to calculate a path if 2 or more graphs are active, and the seeker has to cross a different graph that it is not standing on in order to get to a point that is outside both graphs, I added the code to the very top of Astar.StartPath()…

`
int priority = 0;
int highest = 0;
int lastIndex = -1;

	Node tempStart = null;
	Node tempEnd = null;
	
	for (int i = 0; i < active.graphs.Length; i++) {
	  p.nnConstraint.graphMask = 1 << i;
	  tempStart = active.GetNearest(p.startPoint, 5);
	  tempEnd = active.GetNearest(p.endPoint, 5);
		
	  if ((tempStart == null || tempStart.graphIndex == 0) && (tempEnd == null || tempEnd.graphIndex == 0)) {
	    priority = 0;
	  }
	  if ((tempStart == null || tempStart.graphIndex == 0) && !(tempEnd == null || tempEnd.graphIndex == 0)) {
	    priority = 1;
	  }
	  if (!(tempStart == null || tempStart.graphIndex == 0) && (tempEnd == null || tempEnd.graphIndex == 0)) {
	    priority = 2;
	  }
	  if (!(tempStart == null || tempStart.graphIndex == 0) && !(tempEnd == null || tempEnd.graphIndex == 0)) {
	    priority = 3;
	  }
	
	  if (priority > highest) { 
		lastIndex = i;	
	             highest = priority;
	  }
    }
					
	if (lastIndex != -1) { 
	  p.nnConstraint.graphMask = 1 << lastIndex;
	}
                        ...

`

to determine what graph mask to set where GetNearest() now returns a new NNINfo() if a point is off the graphs. After adding the enabled[i] feature to each graph, disabling them at startup and then re-enabling them .5 seconds later, everything works well with graph masking. The only issue I have to now work on is if the seeker is standing on 2 graphs that overlap each other, how would I not have the start points of its path alternate back and forth from both graphs (creating wiggling paths at its mid points). It is really not a big issue though because the scenario for an end point that sits along 2 overlapping graphs got fixed, and all the seeker really needs is a calculated end point.

                             Sincerely,
                                    Michael S. Lowe