Get_cell_tile_data returns null

Godot Version

4.2.2

Question

Hi! I’m new to Godot and I’m trying to make a basic maze game. I have different color tiles in TileMap for the path you can go on and the walls and I’m trying to have the player check the color of each tile before going on it, to see if its a wall, in which case it cant go there, or a path. I started doing this by adding a custom data layer called “color” and I entered “wall” for the wall blocks and “path” for the others.
However, when I use get_cell_tile_data it returns null. I’ve checked that the tile coords inputted into get_cell_tile_data are real, and I don’t think I have multiple layers on the TileMap.

Here’s my code. It’s in the player scene:

extends CharacterBody2D

@onready var tilemap 
const tile_size = 64
var input_direction
var moving = false

func _ready():
	var player = get_parent()
	var main = player.get_parent()
	tilemap = main.get_node("TileMap") 

	if tilemap == null:
		print("TileMap is null, check path!")
	else:
		print("TileMap successfully found!")


func _physics_process(delta):
	#move
	input_direction = Vector2.ZERO
	if Input.is_action_just_pressed("down"):
		input_direction = Vector2.DOWN
		move()
	elif Input.is_action_just_pressed("up"):
		input_direction = Vector2.UP
		move()
	elif Input.is_action_just_pressed("right"):
		input_direction = Vector2.RIGHT
		move()
	elif Input.is_action_just_pressed("left"):
		input_direction = Vector2.LEFT
		move()
		
	#screen clamping
	global_position.x=clamp(global_position.x,32,1120)
	global_position.y=clamp(global_position.y,32,608)
	

func move():
	print(tilemap)
	if  tilemap != null:
		var target_pos = global_position+tile_size*input_direction
		var tile_coords = tilemap.local_to_map(target_pos)
		var tile_data = tilemap.get_cell_tile_data(0,tile_coords)
		print(tile_coords)
		print(tile_data)


		# Get the tile's metadata (color property)
		var tile_color = tile_data.get("color")
		
		print(tile_color)
		
		if input_direction and not moving and tile_color=='path':
			moving = true
	
			print("move")
			var tween= create_tween()
			tween.tween_property(self,"global_position",target_pos,0.1).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_IN_OUT)
			tween.tween_callback(move_false)
		else:
			print("wall")
	else:
		print("null")
	
	

			
func move_false():
	moving = false


Main scene:
Screenshot 2024-09-21 at 5.39.17 PM

Player scene:
Screenshot 2024-09-21 at 5.39.46 PM

Please help, I’m very new so I have basically no idea what I’m doing and I’ve been trying to find an answer for hours. Thanks!

What do your print statements print out?

This is from the documentation:

Vector2i local_to_map(local_position: Vector2) const
Returns the map coordinates of the cell containing the given local_position. If local_position is in global coordinates, consider using Node2D.to_local before passing it to this method. See also map_to_local.

I would expect your code to contain Node2D.to_local when getting the global_position. You say you checked that the coordinates are real, but what does the print statement say?

You could call this function:

int get_cell_source_id(layer: int, coords: Vector2i, use_proxies: bool = false) const
Returns the tile source ID of the cell on layer layer at coordinates coords. Returns -1 if the cell does not exist.

And check if it returns -1. I say this because get_cell_tile_data can return null on two condition:

Returns the TileData object associated with the given cell, or null if the cell does not exist or is not a TileSetAtlasSource.

1 Like

Thanks for the tip about get_cell_source_id. It did return -1 so I assume I messed up somewhere with global vs local coordinates. The print statement printed coordinates that as global coordinates probably correspond to a real tile but probably not as local is my guess.

I’m trying to figure out where I went wrong and where to actually use to_local.

I tried this which I thought would work but didn’t:

func move():
	if  tilemap != null:
		print("Current position: "+str(position))
		var target_pos = global_position+tile_size*input_direction
		target_pos = to_local(target_pos)

		print("Target position: "+str(target_pos))

		var tile_coords = tilemap.local_to_map(target_pos)

		print("Tile coords: " + str(tile_coords))
		print("Cell source id: "+str(tilemap.get_cell_source_id(0,tile_coords, false)))

		var tile_data = tilemap.get_cell_tile_data(0,tile_coords)

		print("Tile data: " + str(tile_data))

		# Get the tile's metadata (color property)
		var tile_color = tile_data.get("color")

Which printed this:
Screenshot 2024-09-23 at 9.16.39 PM