Alternate shorter path, but not too close to the target?

When I moved my game to newer version of unity, I found that new internal pathfinding works bad in some areas of game level (agent.hasPath && agent.path.corners.length == 0).
I bought Astar, but here now is a little difference, how it works.
Earlier, AIs always move to the edge of a bridge or a river barrier, to follow the enemy and shoot it.
Now, they live this place to find a way to the river, to get closer to enemy as possible. (about 1km path)
Is here any existing setting or method to use old way? I currently only found GetNearest(position) to find nearest node.
How to find nearest point to the target on the nearest nodes (cyan point on the pic)?
I hope pics below will help to convey the idea.

Hi

Are you sure the river was actually connected to the navmesh that the agents stood on (the bridge) when using Unity’s system? I have a hard time seeing that Unity’s system would not find a path that took the agent as close as possible to the target.

Yes, the river and the bridge are the same navmesh. I made simplified geometry of the level (only walkable areas) to use for navmesh calculation. I use it also for recast graph. It looks the same in all cases.
I have tested it many times and did some screenshots.
It always works as I wrote above, in unity 4.7.2.
Yellow vertical 2m lines are unity’s pathfinding path corners.
Friendly AI uses snake’s root transform as destination and finds a path to nearest navmesh edge, closest to snake.
In unity 2017, friendly AI not able to find a path to the snake at all (too long path?).
My question only - is any chance to find this nearest edge to simulate old behavior in unity 2017 with Astar?

Hi

Ah, I see. So Unity had some kind of length restriction.
Well, this is easy enough to emulate, though it requires accessing an internal part of the code to get the distance information:

You create an ITraversalProvider (for more info, see the bottom of this page: https://arongranberg.com/astar/docs/turnbased.html#ITraversalProvider) which prevents the paths from being too long. The G score is the cost to move from the start of the path to that node.

public class MyCustomTraversalProvider : ITraversalProvider {
    public float maxDistance = 100f;
    public bool CanTraverse (Path path, GraphNode node) {
        if ((IPathInternals)path).PathHandler.GetPathNode(node).G > Int3.FloatPrecision * maxDistance) {
            return false;
        }
        return DefaultITraversalProvider.CanTraverse(path, node);
    }

    public uint GetTraversalCost (Path path, GraphNode node) {
        return DefaultITraversalProvider.GetTraversalCost(path, node);
    }
}

Then when you search for a path you will need to assign the traversal provider.

var path = ...;
path.traversalProvider = new MyCustomTraversalProvider();
path.calculatePartial = true;
seeker.StartPath(path, ...);

If you are using one of the built-in movement scripts you can either subclass it and override the SearchPath method, or you can set ai.canSearch to false and do all path searches using a separate script.

Thank you! I’ll try to implement this

1 Like