HOW to grab TileMapLayers (rooms) inside Node2d for Astargrid2d (Example)(figured out)

Question

`How do you make a node2d become a single tilemap layer for astargrid2d? I have individual rooms that are getting premade and dropped into a node 2d.
Set up like:

MainScene
-RoomContainer (node2d)
--Room1 (node2d)
---TileMapLayer
---TileMapLayer
---TileMapLayer
--Room2 (node2d)
---TileMapLayer
---TileMapLayer
---TileMapLayer
-AstarGrid2d (node)

and no matter what I do I cannot get the astargrid2d to register that there are tiles there
`

Im still learning how to code. Someone please, help with this.

I have the code like this:


class_name AStarGridManager

var astar_grid = AStarGrid2D.new()


func _ready() -> void:
	var map_size = get_node("RoomManager")
	
	astar_grid.region = Rect2i(0, 0, map_size.tiles_width, map_size.tiles_height)
	astar_grid.cell_size = Vector2(map_size.cell_width, map_size.cell_height)
	astar_grid.update()
	
	print("hello")

ive tried get children, get index ect and i cant grab the ground layer out of them

AStar2D and AStarGrid2D are points-based traversal algorithms, they do not know anything about tile map layers; you are creating a grid of points unrelated to any tiles. You would need to mark each tile with astar_grid.set_point_solid or fill_solid_region to create blocking points.

Maybe Navigation Agents are closer to what you want?

When AStargrid2d is in the player it seems to need the tile map node to get set point solid.

and it seems to work, I can move and move around objects

code looks like

extends Node2D

@onready var tile_map = $"../TileMap"

var astar_grid: AStarGrid2D
var current_id_path: Array[Vector2i]
var target_position: Vector2
var is_moving: bool

func _ready():
	
	# grid based movement
	astar_grid = AStarGrid2D.new()
	astar_grid.region = tile_map.get_used_rect()
	astar_grid.cell_size = Vector2(16,16)
	astar_grid.update()
	
	#walls and walkable area
	for x in tile_map.get_used_rect().size.x:
		for y in tile_map.get_used_rect().size.y:
			var tile_position = Vector2i(
				x + tile_map.get_used_rect().position.x,
				y + tile_map.get_used_rect().position.y
			)
			
			var tile_data = tile_map.get_cell_tile_data(0, tile_position)
			
			if tile_data == null or tile_data.get_custom_data("walkable") == false:
				astar_grid.set_point_solid(tile_position)

func _input(event):
	
	# camera zoom
	if event.is_pressed():
		if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
			if $playercamera.zoom > Vector2(1,1):
				$playercamera.zoom= $playercamera.zoom - Vector2(1,1)
		
		elif event.button_index == MOUSE_BUTTON_WHEEL_UP:
			if  $playercamera .zoom < Vector2(3,3):
				$playercamera.zoom= $playercamera.zoom + Vector2(1,1)

	
	# movement
	if event.is_action_pressed("left click") == false:
		return
	
	var id_path
	
	if is_moving:
		id_path = astar_grid.get_id_path(
			tile_map.local_to_map(target_position),
			tile_map.local_to_map(get_global_mouse_position())
		)
	else:
		id_path = astar_grid.get_id_path(
			tile_map.local_to_map(global_position),
			tile_map.local_to_map(get_global_mouse_position())
		).slice(1)
	
	if id_path.is_empty() == false:
		current_id_path = id_path
	


func _physics_process(_delta):
	
	#Movement physics
	if current_id_path.is_empty():
		return
	if is_moving == false:
		target_position = tile_map.map_to_local(current_id_path.front())
		is_moving = true
		
	global_position = global_position.move_toward(target_position, 4)
	
	if global_position == target_position:
		current_id_path.pop_front()
		
		if current_id_path.is_empty() == false:
			target_position = tile_map.map_to_local(current_id_path.front())
		else:
			is_moving = false
	

I cant find pathing if i add a Tile Map to the Tile map

my plan is eventually to randomly generate rooms. that I have already made and saved as scenes. In a turn based game where moving 1 tile will be considered 1 turn.

do you think a navigation agent will allow that? like:

navigation agent (put the AStarGrid2d script in this)

For anyone who doesn’t know and wants to know:

I fixed this by: (thanks Nick)

there still is no finite machine, and the player is running physics in current state: will be changed soon

game  (Node2d)
   RoomContainer (Node2d)-------------------(class_name RoomManager)
      GroundLayer (TileMapLayer)
      LowerGroundLayer (TileMapLayer)
      ....Layer (TileMapLayer)
      ....Layer (TileMapLayer)
      ....Layer (TileMapLayer)
      templates (node2d)
         Room1 (node2d)---------------------(class_name RoomChuck)
            GroundLayer (TileMapLayer)
            LowerGroundLayer (TileMapLayer)
            ....Layer (TileMapLayer)
            ....Layer (TileMapLayer)
            ....Layer (TileMapLayer)
         Room2 (node2d)---------------------(class_name RoomChuck)
            GroundLayer (TileMapLayer)
            LowerGroundLayer (TileMapLayer)
            ....Layer (TileMapLayer)
            ....Layer (TileMapLayer)
            ....Layer (TileMapLayer)
   Astargrid2d (node)-----------------------(class_name AStarGridManager)
   Player (characterbody2d)

that is how my files are set up

so to be able to call all the layers into a sigle function is by the following code. This is useful for me because it will allow me to be able to in the future randomly generate rooms that i have already made. Or other things and you can change how you would like to have it done.

RoomManager:

extends Node2D

class_name RoomManager

@onready var ground_layer: TileMapLayer = $GroundLayer
@onready var lower_ground_layer: TileMapLayer = $LowerGroundLayer
@onready var liquid_layer: TileMapLayer = $LiquidLayer
@onready var liquid_top_layer: TileMapLayer = $LiquidTopLayer
@onready var upper_ground_layer: TileMapLayer = $UpperGroundLayer
@onready var ground_object_layer: TileMapLayer = $GroundObjectLayer
@onready var shadow_layer: TileMapLayer = $ShadowLayer
@onready var wall_layer: TileMapLayer = $WallLayer
@onready var object_layer: TileMapLayer = $ObjectLayer


func _ready() -> void:
	var template_rooms:= $templates.get_children()
	var room := template_rooms[0]
	var room1 := template_rooms[1]
	copy_room_to(room, -9, -9)
	copy_room_to(room1, 7, -8)


func copy_room_to(room_template: RoomChunck, x: int, y: int) -> void:
	copy_tilemap_layer_to(room_template.ground_layer, ground_layer, x, y)
	copy_tilemap_layer_to(room_template.lower_ground_layer, lower_ground_layer, x, y)
	copy_tilemap_layer_to(room_template.liquid_layer, liquid_layer, x, y)
	copy_tilemap_layer_to(room_template.liquid_top_layer, liquid_top_layer, x, y)
	copy_tilemap_layer_to(room_template.upper_ground_layer, upper_ground_layer, x, y)
	copy_tilemap_layer_to(room_template.ground_object_layer, ground_object_layer, x, y)
	copy_tilemap_layer_to(room_template.shadow_layer, shadow_layer, x, y)
	copy_tilemap_layer_to(room_template.wall_layer, wall_layer, x, y)
	copy_tilemap_layer_to(room_template.object_layer, object_layer, x, y)

func copy_tilemap_layer_to(from: TileMapLayer, to: TileMapLayer, x: int, y: int) -> void:
	var used_cells := from.get_used_cells()
	
	for cell_pos in used_cells:
		var source_id := from.get_cell_source_id(cell_pos)
		var atlas_coords := from.get_cell_atlas_coords(cell_pos)
		var alternative_tile := from.get_cell_alternative_tile(cell_pos)
		var new_x := cell_pos.x + x
		var new_y := cell_pos.y + y
		
		to.set_cell(Vector2i(new_x,new_y), source_id, atlas_coords, alternative_tile)

RoomChunk:

extends Node2D

class_name RoomChunck

@onready var ground_layer: TileMapLayer = $GroundLayer
@onready var lower_ground_layer: TileMapLayer = $LowerGroundLayer
@onready var liquid_layer: TileMapLayer = $LiquidLayer
@onready var liquid_top_layer: TileMapLayer = $LiquidTopLayer
@onready var upper_ground_layer: TileMapLayer = $UpperGroundLayer
@onready var ground_object_layer: TileMapLayer = $GroundObjectLayer
@onready var shadow_layer: TileMapLayer = $ShadowLayer
@onready var wall_layer: TileMapLayer = $WallLayer
@onready var object_layer: TileMapLayer = $ObjectLayer

AstarGridManager:

extends Node

class_name AStarGridManager

var astar_grid := AStarGrid2D.new()

signal path_found(path: Array[Vector2i])

func _ready() -> void:
	var map_size: TileMapLayer = get_parent().get_node("RoomManager/GroundLayer")

	astar_grid.region = map_size.get_used_rect()
	astar_grid.cell_size = Vector2(16, 16)
	astar_grid.update()

	for x in map_size.get_used_rect().size.x:
		for y in map_size.get_used_rect().size.y:
			var tile_position := Vector2i(
				x + map_size.get_used_rect().position.x,
				y + map_size.get_used_rect().position.y
			)

			var tile_data := map_size.get_cell_tile_data(tile_position)
			if tile_data == null or tile_data.get_custom_data("walkable") == false:
				astar_grid.set_point_solid(tile_position)

func find_path(start: Vector2i, end: Vector2i) -> void:

	if not astar_grid.region.has_point(start):
		return
	if not astar_grid.region.has_point(end):
		return
	
	var id_path := astar_grid.get_id_path(start, end)
	
	if id_path == null or id_path.is_empty():
		return
	
	emit_signal("path_found", id_path)

Player:

class_name Player
extends Node2D

@onready var map_size: TileMapLayer = get_parent().get_node("RoomManager/GroundLayer")
@onready var a_star_grid_manager: AStarGridManager = $"../AStarGridManager"



var current_id_path: Array[Vector2i] = []
var target_position: Vector2
var is_moving: bool = false

func _ready() -> void:
	# Connect to the signal
	a_star_grid_manager.connect("path_found", Callable(self, "_on_path_found"))

func _input(event) -> void:
# Zoom handling
	if event.is_pressed():
		if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
			if $PlayerCamera.zoom > Vector2(1,1):
				$PlayerCamera.zoom= $PlayerCamera.zoom - Vector2(1,1)
		elif event.button_index == MOUSE_BUTTON_WHEEL_UP:
			if  $PlayerCamera .zoom < Vector2(3,3):
				$PlayerCamera.zoom= $PlayerCamera.zoom + Vector2(1,1)

# Movement handling
	if event.is_action_pressed("left click"):
		a_star_grid_manager.find_path(
			map_size.local_to_map(global_position),
			map_size.local_to_map(get_global_mouse_position())
			)

# **Callback for path signal**
func _on_path_found(path: Array[Vector2i]) -> void:
	if path.is_empty():
		return
	
	current_id_path = path
	is_moving = true
	#print("Received new path:", path)

func _physics_process(_delta) -> void:
	if current_id_path.is_empty():
		return
		
	if not is_moving:
		target_position = map_size.map_to_local(current_id_path.front())
		is_moving = true
	
	global_position = global_position.move_toward(target_position, 3)
	
	if global_position == target_position:
		current_id_path.pop_front()
		
		if current_id_path.is_empty():
			is_moving = false
		else:
			target_position = map_size.map_to_local(current_id_path.front())
			#print("Moving to:", target_position)