ITraversalProvider not working in 5.4.4

  • A* version: 5.4.4
  • Unity version: 6000.2.8f1

Hi, I upgraded A* Pathfinding Project to the new version, and tried to implement the changes to NN constraint and traversal providers. Goal is to have large units in 2D use 2 tiles horizontally when moving, so the x+1 tile needs to be available for the unit as well.

The ITraversalProvider I created worked well in the previous version of A*, but is now ignored by pathfinding:

Path path = ABPath.Construct(start + new Vector2(0.5f, 0.5f), end + new Vector2(0.5f, 0.5f));

// Add offset for large units
if (_isLarge)
{
    ITraversalProvider traversalProvider = LargeUnitTraversalProvider.IsLarge();
    
    var constraint = path.nearestNodeConstraint;
    constraint.traversalProvider = traversalProvider;
    
    path.traversalConstraint.traversalProvider = traversalProvider;
    path.traversalCosts.traversalProvider = traversalProvider;
}

AstarPath.StartPath(path);
AstarPath.BlockUntilCalculated(path);

And the ITraversalProvider:

class LargeUnitTraversalProvider : ITraversalProvider
{
    private Vector2Int[] _shape;

    public static LargeUnitTraversalProvider IsLarge ()
    {
        var shape = new LargeUnitTraversalProvider
        {
            _shape = new[]
            {
                new Vector2Int(0,0),
                new Vector2Int(1,0)
            }
        };

        return shape;
    }

    public bool CanTraverse (ref TraversalConstraint traversalConstraint, GraphNode node)
    {
        GridNodeBase gridNode = node as GridNodeBase;

        // Don't do anything special for non-grid nodes
        if (gridNode == null) return DefaultITraversalProvider.CanTraverse(ref traversalConstraint, node);
        int x0 = gridNode.XCoordinateInGrid;
        int z0 = gridNode.ZCoordinateInGrid;
        var grid = gridNode.Graph as GridGraph;

        // Iterate through all the nodes in the shape around the current node
        // and check if those nodes are also traversable.
        foreach (var node2 in _shape)
        {
            var inShapeNode = grid.GetNode(x0 + node2.x, z0 + node2.y);
            if (inShapeNode == null || !DefaultITraversalProvider.CanTraverse(ref traversalConstraint, inShapeNode)) return false;
        }
        
        return true;
    }
}

What am I missing here to re-enable 2-tile large unit movement on a grid?

Found the issue:

if (inShapeNode == null || !DefaultITraversalProvider.CanTraverse(ref traversalConstraint, inShapeNode)) return false;

Should instead be:

if (inShapeNode == null || !inShapeNode.Walkable) return false;

Now it’s working.

The nearest node constraint is not required either, just the traversalConstraint.traversalProvider.

Hi

Yes indeed.

Though, the even better option is:

if (inShapeNode == null || !traversalConstraint.CanTraverseSkipUserFilter(inShapeNode)) return false;

as that will include all other options of the traversal constraint (like tag filters and such).

I’ll fix the example in the documentation in the next update.

1 Like