Get position on navmesh

I was using code below to get position on a navmesh.
To my surprise the node obtained by GetNearest may not ContainsPoint that was used to get this node.
And I’m not talking about border situation when the point is outside navmesh.
This point was clearly inside navmesh.

public bool GetPositionOnNavmesh(Vector3 position,PathGraph pathGraph,out Vector3 onNavMeshPosition) {

    NavGraph graph = GetGraph(pathGraph);
    NNInfoInternal nodeInfo = graph.GetNearest(position);
    MeshNode meshNode = nodeInfo.node as MeshNode;
    if (meshNode == null || !meshNode.ContainsPoint((Int3)position)) {
        onNavMeshPosition = Vector3.one * float.MinValue;
        return false;
    }
    onNavMeshPosition = meshNode.ClosestPointOnNode(position);
    return true;
}

That seems weird. Do you happen to have a screenshot of the issue?

Also. What version are you using?

Version 4.0.10

The bug happens close to an edge between two nodes. Usually when I walk back and forth crossing the edge - it will happen.
I was using breakpoint to catch this bug, as you can see on a screenshot. Also I checked that meshNode was not null.

Ah. I see.
This is actually expected.

The GetNearest method will return the closest node. On a sloping surface this might not be the node that the character is above.

The GetNearest call will find the point where the red line meets the blue surface (because that is the closest point) while the ContainsPoint method checks if the point is inside the node when seen from above.

There is an option for the GetNearest method to check for the nearest node in XZ space however.
Either you can toggle it in the RecastGraph globally:

or you can create an NNConstraint and set the corresponding property:

 var nn = NNConstraint.Default;
 nn.distanceXZ = true;
 var info = AstarPath.active.GetNearest(point, nn);

Also I would like to straighten some things.

GetNearestNode returns a closest node but it’s not the closest node by projecting the point onto it (like in your picture)?

So by using your picture (modified):

There is no way to get C node found by the shortest projection of point onto node polygon ?

Also default Constraint should return A and xz constraint should return B ?

I have edited my previous post, I have written something that was not a bug after further testing.

So I decided to do

NNConstraint xzConstraint = NNConstraint.Default;
xzConstraint.distanceXZ = true;

As you suggested unfortunately new bug appeared.
Code below generate result as on the picture.

public bool GetPositionOnNavmesh(Vector3 position, PathGraph pathGraph, out Vector3 onNavMeshPosition) {
    NavGraph graph = GetGraph(pathGraph);
    NNConstraint xzConstraint = NNConstraint.Default;
    xzConstraint.distanceXZ = true;
    NNInfoInternal nodeInfo = graph.GetNearest(position,xzConstraint);
    MeshNode meshNode = nodeInfo.node as MeshNode;
    if (meshNode == null || !meshNode.ContainsPoint((Int3)position)) {
        onNavMeshPosition = Vector3.one * float.MinValue;
        return false;
    }
    onNavMeshPosition = meshNode.ClosestPointOnNode(position);
    return true;
}

I draw a white line from position to onNavMeshPosition.
You can see the line under the robot.

As you can see on the image the onNavMeshPosition ends up being on another area under the current node. It does not appear in all places where there are multiple level areas. Sometimes current node is dominant.

Ok, I investigated the code a bit and it turns out there were several bugs relating to the distanceXZ setting.
This is the result I am getting now after the bugfixes.

Great.
Btw. when are you planning to release the update. No need to rush since as I remember there were some bugs with “get portals”. And it’s always better to wait a little longer and obtain bugles release.