X-com 2 style graph. Allow for thin walls

Hey there.

In the modern xcom games it seems the path can be blocked between two adjacent nodes(squares), and I was wondering if that was possible with the layered grid graph?

To block a path with the layered grid graph I must block the entire square, but I was wondering if there was a way to only block the path between the two nodes? This would allow for thin walls, similar to xcom which would be ideal for my current project.

Cheers

Hi

When the grid graph is normally scanned this is not possible. However it is possible to do using code.
Something like this:

AstarPath.active.AddWorkItem(new AstarWorkItem(ctx => {
    var node1 = AstarPath.active.GetNearest(position1).node as LevelGridNode;
    var node2 = AstarPath.active.GetNearest(position2).node as LevelGridNode;
    // Remove the connection between these 2 nodes
    for (int i = 0; i < 4; i++) {
        if (node1.GetNeighbourAlongDirection(i) == node2) {
             node1.SetConnectionValue(i, LevelGridNode.NoConnection);
        }
        if (node2.GetNeighbourAlongDirection(i) == node1) {
             node2.SetConnectionValue(i, LevelGridNode.NoConnection);
        }
    }

    // Required to update some metadata after all node connections have been changed
    ctx.QueueFloodFill();
}));

Cheers for your reply, I will give this a go!

Hey!

Thanks for that, it works quite well. The only Issue I am having now is caused by the funnel modifier because it tries to cut corners and units get stuck.

I am going to experiment a bit though, perhaps I can cut connections next to corners and doorways to allow a wider berth unless you have a nicer solution.

Cheers

Hi

There is a setting on the grid graph called ‘cut corners’, have you tried disabling that? I’m not sure if it will change the output of the funnel modifier though. I think it should be equivalent.

It appears the cut corners option is only available on the grid graph, and not the layered grid graph.
Perhaps there is a way to turn off funneling when pathing through nodes that have cut connections?

Do you think you could show a screenshot of it happening?

@aron_granberg is this still the recommended solution for thin walls in a layered grid graph?

If yes then where do I put the code you shared so that when I hit “Scan” in scene view this code would be executed and the thin walls will be accounted for.

Thanks

This solution was able to work for me to detect thin walls.

I added a script to the walls and fed in postion1 and position2 from the sides of the wall nearest to the nodes that needed to be disconnected. I then created a function to break the connection and it works perfect.

Thanks.

1 Like

If anyone else is looking for something like this; here is a quick starter script. Just pop it onto a game object and set up your layers. It hooks into the AStar component so it will work whenever you rescan in game:

using UnityEngine;
using Pathfinding;

public class WallPostProcessor : MonoBehaviour
{
    GridGraph graph;
    public LayerMask wallLayers;

    private void OnEnable()
    {
        // Subscribe to AStar & Manually Re-scan
        AstarPath.OnLatePostScan += WallFinder;
        AstarPath.active.Scan();
    }

    private void OnDisable()
    {
        // Unsubscribe
        AstarPath.OnLatePostScan -= WallFinder;
    }

    private void WallFinder(AstarPath script)
    {
        graph = AstarPath.active.data.gridGraph;

        foreach (GraphNode node in graph.nodes)
        {
            var nodePos = (Vector3)node.position;
            // offest lifts the collision check off the floor
            var offset = new Vector3(0, 0.5f, 0);

            // Break Connections if Wall is in the way
            node.GetConnections(otherNode =>
            {
                // Find the point midway between connected nodes
                var halfway = nodePos + (((Vector3)otherNode.position-nodePos)/2);
                // Check for any object between connected nodes
                if (Physics.CheckSphere(halfway+offset, 0.1f, wallLayers))
                {
                    GraphNode.Disconnect(node, otherNode);
                }
            });
        }
    }
}

1 Like