How do you only return nodes that can be reached using Astar.active.GetNearest()?

Hello,

I’m trying to code a basic moveTo(position) function for my AI which uses the RecastGraph from A* Pro. The basic logic (simplified a bit) to get the location to move to is as follows:

`
Pathfinding.NNConstraint mWalkableConstraint = new Pathfinding.NNConstraint();
mWalkableConstraint.walkable = true;
Pathfinding.Node node;
node = AstarPath.active.GetNearest (moveToPosition, mWalkableConstraint);
if(node.walkable){
	Debug.Log("Node is walkable");
}else{
        //Should never get here
	Debug.LogWarning("Node is NOT walkable");
}
moveToPosition = (Vector3)node.position;
target = moveToPosition;
`

Note that I’m extending the AIPath script provided with the A* library so setting the target should just move to that position. (I modified it a bit so target takes a Vector3 and not just a Transform). The problem I’m having is that the target to walk to is being set to nodes that cannot be reached (e.g., are inside a solid building that you shouldn’t be able to go inside). When I look at the paths in the debug game view the node is outlined in red but for some reason it’s still labeled as walkable. Of course the character just walks up to the wall of the building and can never actually reach the position.

Does “walkable” mean “reachable”? If so, why do the nodes that can’t be reached have walkable set to true. If “walkable” does not mean “reachable”, how do I ensure that the position can be reached and that the returned node is actually reachable? Is there a way to generate the recast graph so disconnected nodes that are not reachable from the main mesh are removed? If there is a way to do this from the editor interface and if so how do you specify what the main mesh is?

Thank you for your help!

PS The new forums are a fantastic upgrade over the old ones.

Hi

First of all, you are not setting NNConstraint.constrainWalkability to true, it is ok since that is the default value, but you should be aware that the setting exists.
Walkable means that the node can be traversed, but not necessarily that it can the reached from some other position. For that, I use the concept of areas, one area is a connected subgraph (i.e all nodes in it can reach all other nodes).
In the editor, unwalkable nodes are shown using red cubes (if you switch on Show Unwalkable Nodes in A* Inspector -> Settings). However on recast graphs, there are usually none.
Areas are shown by giving the nodes a different colored outline (the first color is blue, the second one red, etc. can be edited in A* Settings), if you have the debug mode Areas selected (A* Settings -> Debug Mode).

What you should do is to first get the area id of the node you want to path from:
//[Edited example to work with version 3.2] Node node = AstarPath.active.GetNearest (moveFromPosition, NNConstraint.Default).node; int areaID = node.area;
Then you want to configure the NNConstraint to only return nodes which can be reached from the start node:
NNConstraint nn = new NNConstraint (); nn.constrainArea = true; nn.area = areaID;
Now if you use that NNConstraint, only nodes which are reachable from your start node will be returned.

There is currently no way to remove a specified area completely from the graph, there is a post in the feature request category about that: http://www.arongranberg.com/vanillaforums/discussion/28/delete-some-areas-of-the-world#latest

Yup, these forums are like a million times better! Too bad I wasn’t able to import the posts from the old forums though.

Hope it helps!

Hi,

Digging up an old solution here, but I get a conversion error trying to convert NNInfo to Node on the first line: Cannot implicitly convert type ‘Pathfinding.NNInfo’ to ‘Pathfinding.Node’. An explicit conversion exists (are you missing a cast?).

Looking at the class docs it does appear that NNConstraint.Default returns a node, so I must be missing something?

Hi

Version 3.2 removed the implicit cast with this motivation:

Conversions between NNInfo and Node are now explicit to comply with the rule of "if information might be lost: use explicit casts".

It is also mentioned in the upgrade guide for 3.1.x → 3.2.x

If you have been getting the closest node to a point with

Node node = AstarPath.active.GetNearest(somePosition);

You will now have to either explicitly cast from NNInfo (which the GetNearest function actually returns) or get the node by the .node field

Node node = AstarPath.active.GetNearest(somePosition).node;

Exactly which page in the docs uses an implicit cast? Nice to know so I can update it with correct information.

Ah, thanks for the fast reply, that’s very helpful - I should really make a habit of checking update notes.

The docs part I was reading was at the bottom of http://arongranberg.com/astar/docs/class_pathfinding_1_1_n_n_constraint.php

I’m not particularly at interpreting class documentation, it’s still fairly new to me.

Would it be worth a suggestion/feature request for an bool IsReachable function? For, i.e., point-and-click implementations it would be very useful.

http://arongranberg.com/astar/docs/class_pathfinding_1_1_path_utilities.php#a78c136feba9843851f499b21c86c1731

That function will work unless you are using tags. Then it might return true in some cases when it should not (the function does not even take a param describing the enabled tags so that’s quite obvious)

Excellent - I’m not using tags so all good, thanks again Aron.