New TileMapLayers in 4.3 and AStarGrid2D

Godot Version

4.3.dev6

Question

I am trying to implement the AStarGrid2D navigation in my game on 4.3. In my scene, I have 2 TileMapLayers: “Ground” and “Walls.” “Ground” contains the tiles that have navigation layers, and “Walls” is for collisions. Eventually I would like to implement other layers, like decoration layers.

From this post, I learned that Godot’s TileMap layers are not designed to function with features like navigation and collision, instead forcing everything to use Layer 0 for every feature.
https://www.reddit.com/r/godot/comments/10n14l8/question_how_to_actually_use_different_physics

To get around this limitation, according to this post, you need to somehow combine all tilemaps layers into one tilemap layer before you’re able to use navigation on it - meaning I’ll need to somehow read through all my tilemaps and set each tile on the combined layer’s data to match the other layers. However, I have no clue how to do this.
https://forum.godotengine.org/t/navigationagent2d-with-layered-tilemap/47673/3

Right now I have the following:

	public void UpdateDataLayer()
	{
		foreach (TileMapLayer i in Layers)
		{
			var allTiles = i.GetUsedCells();
			foreach (var tile in allTiles)
			{
				var cellTile = i.GetCellTileData(tile);
			}
		}
	}

Which should loop through all my TileMapLayers and get the used tiles, but I don’t actually understand how to tell which tiles are collidable, which are navigable, and which have other data properties so that I can assign them to my base “DataLayer.”

As far as I know, once I’ve got my combined DataLayer I should be able to use AStarGrid2D to implement navigation, but I’m stalled out right now due to being unable to combine layers.

Does anyone know how I can achieve this?

AStarGrid2D is a very simple cell-based waypoint system, it is not affected by any of the issues in those linked discussions that talk about the TileMap issues with its wrong use of navigation mesh specifically.

For AStarGrid2D you set your Rect2 and the cell size to match your TileMap. Since all those AStarGrid2D cells are traversable by default you now loop over your TileMap used cells and set those cells with a collision polygon to “solid” with the AStarGrid2D function and that is it for the basic setup.

The issues and discussion you linked talk about why the TileMap and TileMapLayers are so dysfunctional for navigation mesh surfaces. You can not stack or overlap navigation mesh while the TileMapLayers give users the idea that they can. The TileMapLayers and TileMap editor sets users up to fail with navigation and the frustating part is that the TileMap just giggles in silence when they do and the users are confronted with a flood of errors from the navigation mesh system.

1 Like

I see, that makes sense. So by doing the following:

		for(int x = 0; x < regionSize.X; x++)
		{
			for(int y = 0; y < regionSize.Y; y++)
			{
				var tilepos = new Vector2I(x + regionPosition.X, y + regionPosition.Y);

				var tiledata = currentTilemap.GetCellTileData(tilepos);

				if(tiledata == null)
				{
					if (tiledata.GetNavigationPolygon(0) != null)
					{
						aStarGrid.SetPointSolid(tilepos);
					}
				}
			}
		}

I was able to scan through my tilemap and set up the solids in my grid. Unfortunately I don’t think AStarGrid2D is going to be usable for my project, and it seems like I will have to go with the navigationagent, as when I GetIdPath the AStarGrid only returns a single value along the path to the nearest tile, not all the way to the target object. Since the length of GetIDPath is always only 2 (the current position and the next tile position,) the AI agents are unable to navigate around obstacles and will walk right into them and stop. AStarGrid2D may not be made for navigation in that way, so I believe I’ll need to look elsewhere.

What would you say would be the best way to combine multiple tilemaplayers into one master layer that I can run the NavigationAgent2D on? As far as I can tell, it seems the best way would be to create a black and white tileset that’s either a solid or not, set the whole tilemaplayer to solid, then loop through each tilemap and check for a NavigationPolygon, setting those to the walkable tile. Then I’d just need to put this layer beneath all others so it would be invisible.

AStarGrid2D is just a grid-based variant of AStar2D and both will give you a full waypoint path if asked. Not sure why you should only get a two point path, maybe your setup skipped something? You can find demo projects for both in the official Godot demo project repo on git or on the asset lib, both give you full waypoint paths.

If you want to stay with the navigation mesh system what you need to do is make sure that no navigation mesh surface overlaps. If you have parts that need to overlap, e.g. because they are build around pseudo 2D verticality, you need to seperate the navigation mesh surfaces by using different navigation maps and moving the affected navigation regions to those.

The original TileMap node by default moved each of its internal layer to its own navigation map. The newer TileMapLayer nodes messed that up again and now you need to do the separation yourself with the NavigationServer API.

1 Like

Ah, I see. I was using the wrong method to find the path. But I’m now aware that the AStarGrid2D can only accommodate entities that are 1x1 cell in size, which doesn’t work for my project, so I’m going to have to use the normal navigation system anyway. Thank you for your help, though. AStarGrid2D seemed like it would have been very useful.