Is there a way to check if my agent can reach it's destination?

  • A* version: [5.3.4]
  • Unity version: [2023.3.42f]

Hey there!

Been using a* on my first person 3d project, so far it’s been great. I have a question: is there a simple way to check if my agent’s graph can actually reach it’s destination? (for example, I would like my NPCs to act differently if theyr destinatino is ona different floor).

I did try using IsPathPossible but as for now it’s always returns false even when the NPC clearly has direct path towards the target, so I’m probably unfamiliar with something. Here’s an example for what I’ve been trying to do:

    var startNode = AstarPath.active.GetNearest(transform.position).node;

    var endNode = AstarPath.active.GetNearest(newDestination.transform.position).node;

    // Check if a path is possible on the graph

    if (PathUtilities.IsPathPossible(startNode, endNode))

    {

        followerEntity.canMove = true;

    }

Daniel

Hi

That code looks correct.

I’d check if you get the nodes you expect, using e.g.

Debug.DrawRay((Vector3)endNode.position, Vector3.up, Color.red);

I’m still struggling to get this right. The debug looks like the nodes are in the correct places (there’s a very clear walkable path between them), but still it returns false 99% of the time (sometime it would start walking and stop in the middle). When I manually drag the object around with my mouse, sometimes the agent will find it, return true, and go to the destination—but these situations are very hard to reproduce, and I can’t find the logic behind it.

I’m wondering if there’s a mismatch between the transform.position and the node I’m turning it into? I’ve tried to add constraints, but it’s still not working. Maybe there’s a specific constraint that I should be using in order to make sure the nodes are indeed positioned correctly on the graph? Right now I’m trying this, but it’s still no go:

public void MoveTowardsDestination(GameObject newDestination)
{
followerEntity.destination = newDestination.transform.position; 
NNConstraint constraint = NNConstraint.Walkable;
var startNode = AstarPath.active.GetNearest(transform.position, constraint).node; 

var endNode = AstarPath.active.GetNearest(newDestination.transform.position, constraint).node; 

if (startNode == null || endNode == null) 

{ 

    Debug.LogError($"{gameObject.name}: Could not find valid path nodes."); 

    followerEntity.canMove = false; 

    return; 

} 

float distanceToTarget = Vector3.Distance(transform.position, newDestination.transform.position); 

float closeEnoughThreshold = 2f; 

if (PathUtilities.IsPathPossible(startNode, endNode) || distanceToTarget <= closeEnoughThreshold) 

{ 

    followerEntity.canMove = true; 

    Debug.Log($"{gameObject.name}: Moving to destination. Distance: {distanceToTarget:F2}m | StartArea: {startNode.Area}, EndArea: {endNode.Area}"); 

} 

else 

{ 

    followerEntity.canMove = false; 

    Debug.LogWarning($"{gameObject.name}: Cannot reach destination. Distance: {distanceToTarget:F2}m | StartArea: {startNode.Area}, EndArea: {endNode.Area}"); 

} 
}

Do you have multiple overlapping graphs in the scene by any chance?

Yes, I have two: for large and small objects. I removed one and it tottaly works! Thanks!

Is there a way to use this logic without removing one of them, though?

Yes, you’ll have to specify which graph to use.

In the latest version:

var constraint = NearestNodeConstraint.Walkable;
constraint.graphMask = GraphMask.FromGraphIndex(0); // For example
var startNode = AstarPath.active.GetNearest(transform.position, constraint).node; 

or in your older version

var constraint = NNConstraint.Walkable;
constraint.nnConstraint.graphMask = GraphMask.FromGraphIndex(0); // For example
var startNode = AstarPath.active.GetNearest(transform.position, constraint).node; 

See also GraphMask - A* Pathfinding Project

You can also get this info from the FollowerEntity:

var constraint = followerEntity.pathfindingSettings.ToNearestNodeConstraint();

IIRC this only works in 5.4+, though.

Thank you so much! I apreciate your time, A* is awesome :slight_smile:

1 Like

Glomming on this, is there an easy way to find if an agent can get within a certain radius of a point? I will admit that I haven’t tried this in A* yet, but one of my issues with the Unity NavMesh pathfinding was that I had enemies that could attack over a certain distance, and I would want to see if they could get close enough to a target, even if it meant attacking over a non-traversable state, and the function to find if there was a path only accepted a given position, so I’d get enemies that wouldn’t target turrets because they could only get within punching distance, not on top of the turret, or they’d get stuck on a turret they couldn’t get close enough to punch because they did try to get close enough without a complete path, and then find they couldn’t reach it.

I believe you’re looking for endingConditions. Directly from the documentation is this exact example funny enough:

The ending condition determines when the path has been completed. Can be used to for example mark a path as complete when it is within a specific distance from the target.

If this doesn’t fit your usecase fully, let me know :+1: Ideally in a new thread. (I’d also advise placing a link to this thread in your post so that Discourse links the two threads together for future folks who run across this)