Support Forum

Handle units of greater than 1 grid size

Hello, thanks for this great library.

I am making a 2D tower defense game. I have a grid graph where units of 1 grid size works well. However, I also have units of 3x3 size that should not be able to go through a 1 square opening. I have tried the traversalProvider approach:

    Vector3 closest_pos = (Vector3)AstarPath.active.GetNearest(target.transform.position, 
             NNConstraint.Default).position;
    ABPath ab_path = ABPath.Construct(transform.position, closest_pos, OnTraversalPathComplete);
    ab_path.calculatePartial = true;
    ab_path.traversalProvider = GridShapeTraversalProvider.SquareShape(grid_size);
    seeker.StartPath(ab_path);

However, if there is no path to the final destination, the 3x3 units will not calculate a partial path.
Basically, I need large units to be able to handle cases were

  1. there is a 3 unit wide path to destination,
  2. There are no 3 unit wide paths to destination, and
  3. There is no path of any width

With code above only #1 works.

why using A* for TD game?
But if you need pathfinding for TD you can use 2rd grid for your 3x3 units with node size = 3.
Or do like me in my rts game add a Tag no walkable for 3x3 units and set this tag on nodes around no walkable nodes.

The TD game is similar to RTS in that there is no predefined path for the enemies to take. you can route them based on how you build.

For a 2nd grid, how would that work if I have buildings that are 1x1? If I have two 1x1 buildings spaced 3 units apart, they could occupy 2 nodes of the 2nd grid making the unit think its unwalkable. Sorry if this is a newbie question.

I’m also not sure the tagging approach would work for similar reasons. Because the player can place buildings anywhere. If i just tag all tiles adjacent to all buildings, it would mean enemies can’t walk up to the buildings (maybe I’m not understanding it).

I think the best approach for my case is to find the path (even if a partial path), and then loop through each segment of the path and check if its 3 units wide. But am I able to access each segment of the path in this way?

“I’m also not sure the tagging approach would work for similar reasons. Because the player can place buildings anywhere. If i just tag all tiles adjacent to all buildings, it would mean enemies can’t walk up to the buildings (maybe I’m not understanding it).”
But you can change tags where and when you need. Place your building, set this nodes unwalkable ans set tag for nodes around “no walkable for 3x3”. So your 1x1 units can pass, but not 3x3 units. I will make a screenshot for you in 10-15 min, it will help you

Imagine you have 2 tags. "Ground "and “NotFor3x3”

So NotFor3x3 yellow color nodes
Ground no collor.
So 1x1 units walk on all tags. "Ground "+“NotFor3x3”
3x3 units walk only on "Ground " tag.
Building can place on all tags .
Blizzard do this in sc1 and warcraft 3

1 Like

I see now. Thank you for the screenshot and your time to write it up - it did help a lot.

The part that I was hung up on was how a 3x3 unit would walk up to a building and attack it (at melee range), but if I understand correctly the 3x3 unit’s “collider” boundary can still extend into the “NotFor3x3” tiles. So in terms of pathfinding, the size of the 3x3 unit is actually 1x1, right?

yes. Just dont walk on NotFor3x3 nodes.

Apologies if this is veering a bit off topic now. I’ve been looking around for similar implementations but not seeing it and was wondering if you could share a bit more how you solved this problem.

I see the tags being marked around my buildings when I place them at run time. But when the units calculate their path, the tag seems to disappear and the pathing ignores the tags.

This is the code I use to add a tag to each node around the tower:

       AstarPath.active.AddWorkItem(ctx => {
            var grid = AstarPath.active.data.gridGraph;
            foreach (Vector3 pos in pos_around_tower) {
                GraphNode node = AstarPath.active.GetNearest(pos).node;
                node.Tag = 1;

                GridNodeBase n = node as GridNodeBase;

                grid.CalculateConnectionsForCellAndNeighbours(n.XCoordinateInGrid, n.ZCoordinateInGrid);
            }
        });

I set the seeker on my 3x3 unit to not traverse Tag 1.

However, my large 3x3 units seem to be ignoring the tagging and still traverse through it. Am I overlooking something?

Tag setting:
05%20PM

Seeker settings:

@aron_granberg, if you have any suggestions

in my project i do like that

GraphNode node = graph.GetNearest(Vector3).node;
node.Tag = 1;

Without calculate connection

I ended up creating a new gridgraph for larger units and having a buffer around each building that makes it not traverseable. The issue I ran into with tagging at runtime is whenever I rescanned a part of the graph it would erase the tags. I’m sure there’s a way around it but having a separate gridgraph was easiest in my case.

Hi

There is the ‘erosion uses tags’ feature which assigns a tag based on the distance to all obstacles. Maybe you can use that?

The traversal provider would work too of course and is probably simpler.

And based on the distance to other tags ? So i have buildings 3x6 nodes and i need set tags to all nodes around this 3x6 building with distance like 5-6

Not based on the distance to other tags.
But I would assume that the buildings would all be unwalkable, correct? So one node from the building it would set one tag, then two nodes from the building it would set another tag, and so on (up to the erosion limit).