LayeredGridGraph custom CalculateConnections()?

Dear :blush:

Im working on a minecraft-like game. The terrain is for now represented as:
Tile[,] mapIndex = new Tile[widht, height, depth];

A tile contains its position, materialId and also its walkability.

After some investigations i was able to rewrite the SampleCell() function like this

        LinkedLevelNode SampleCell(int x, int z)
        {
            if (World.instance == null)
                return new LinkedLevelNode();

            LinkedLevelNode[] nodes = new LinkedLevelNode[World.instance.mapHeight];
            int nodeCount = 0;

            for (int y = 0; y < World.instance.mapHeight; y++)
            {
                if (World.instance.mapIndex[x, z, y].walkable)
                {
                    nodes[nodeCount] = new LinkedLevelNode();
                    nodes[nodeCount].position = new Vector3(x, y + 1f, z); //Assets.UltimateIsometricToolkit.Scripts.Utils.Isometric.IsoToUnitySpace(new Vector3(x, y + 1f, z));
                    nodes[nodeCount].height = 0.5f;
                    nodes[nodeCount].walkable = true;

                    if (nodeCount > 0)
                    {
                        nodes[nodeCount - 1].next = nodes[nodeCount];
                    }

                    nodeCount++;
                }
            }

            return nodes[0];
        }

And as a result, it finally works! I can move my AI from every tile to every tile. But the AI ​​should only be able to go up and down stairs (see picture).

I think that means I need to rewrite the CalculateConnections () function so it will just connect tiles at the same height and then I’ll need a logic for connecting nodes to stairs later at RUNTIME up and down.

I’ve really tried to do it myself, but I can not figure out how connections work. All I see is “node.SetConnectionValue (dir, conn);”. I thought there was something like node.SetConnection (ie Dir.UP, dir.Left …), but it looks a lot more complicated.

In addition, I ask how it is possible to have only four connections? What if a tile needs to be connected up, down, forward, back, left, and right?

Picture shows game-world, graph and a stair:

I really hope you understand what my goal is. I am very grateful for any help, tips and information.

Thank you very much for your time!
Greetings

Okay i did some progress!

Within RecalculateCell() i added(just for debugging):
node.Tag = (uint)lln.position.y;

Current CalculateConnections() with only little changes:

        public void CalculateConnections(int x, int z, int layerIndex)
        {
            var node = nodes[z * width + x + width * depth * layerIndex];

            if (node == null) return;

            node.ResetAllGridConnections();

            if (!node.Walkable)
            {
                return;
            }

            for (int dir = 0; dir < 4; dir++)
            {
                int nx = x + neighbourXOffsets[dir];
                int nz = z + neighbourZOffsets[dir];

                // Check for out-of-bounds
                if (nx < 0 || nz < 0 || nx >= width || nz >= depth)
                {
                    continue;
                }

                // Calculate new index
                int nIndex = nz * width + nx;
                int conn = LevelGridNode.NoConnection;

                for (int i = 0; i < layerCount; i++)
                {
                    GraphNode other = nodes[nIndex + width * depth * i];

                    if (other == null || !other.Walkable)
                        continue;

                    Debug.Log(other.position.y);

                    if ((node.position.y == other.position.y))
                    {
                        conn = i;
                    }
                }
                
                node.SetConnectionValue(dir, conn);
            }
        }

On the pathfinder under settings i changed “Max Nearest Node Distance” from 100 to 0.

Now AI can only move on one height :blush:

Only thing i need to find out now is how to add a “stair-connection” at runtime?

And why do I get something like 2000, 4000, 22000 … instead of 2,4,22 … at node.position. Why does Int3 multiply it by 1000?

Thank you so much!

Hi

I think you have been confused by how the layered grid graph is represented here.
The layered grid graph is not represented like a voxelized world, where every node must lie precisely at an integer coordinate like in minecraft (for example). Instead it is represented as a grid of cells or “pillars”, where each pillar can contain multiple nodes at different arbitrary y coordinates. A node is treated as a surface, and its connections are thought of similarly to “if I walk right on this surface, on which node will I end up”.

Looking at your world, I do not see any overhangs. I.e is there at any point in your world a case where the character could stand at multiple y coordinates in a single cell? Like for example if there was a cave in the world. If not, then you could use a normal grid graph.

The SetConnectionValue works in this way. The value of conn is either LevelGridNode.NoConnection if the character cannot move in that direction, or it is set to the index of a node in the pillar in that direction.
image
In the pretty horribly drawn example above, node A sets its connection to the right to 1, because node B is the second (index 1) node in that pillar (counted from the bottom). However B sets its connection to the right to 0 because node C is the first node in that pillar (as the underground cave ended, there was no need for any node below node C).

You probably have this figured out from the docs already, but the ‘dir’ parameter in the SetGridConnection method relates to actual directions like this
image

Node.position is a world space position represented using integer coordinates. This is done to avoid some floating point calculations in the fast path of the system and to make some calculations easier to reason about (floating point math can be really horrible). You can convert between Int3 and Vector3 using an explicit cast. var v3 = (Vector3)new Int3(1000,2000,3000);

That is probably a bad idea. That means all get nearest node queries will fail, most likely all your path requests will fail because of this.

1 Like