Godot Version
4.3
Question
I have been trying to retrieve custom data from tiles in a tileset upon collision. The game is 2d and plays from a side view much like a 2d platformer.
Everything seemed to be going smoothly, and i came up with the following code (I’ll update it to TileMapLayer later on):
var surface_type : int
if collision_collider is TileMap:
var tilemap = collision_collider as TileMap
var collision_point = collision_info.get_position()
# Convert collision point to local coordinates of the tilemap
var local_point = tilemap.to_local(collision_point)
# Get the tile coordinates from the local point
var tile_coords = tilemap.local_to_map(local_point)
# Access the custom data from the TileSet
var data = tile_map.get_cell_tile_data(0, tile_coords)
# Get the surface type data
surface_type = data.get_custom_data_by_layer_id(0)
print(surface_type)
Straight away the problem with this became apparent as if i hit a wall to the left or the ceiling i get the following error:
“Attempt to call function ‘get_custom_data_by_layer_id’ in base ‘null instance’ on a null instance.”
The issue is, i think because the TileMap indexes from top left to bottom right. Basically if i hit something below or to the right, it seems to identify the correct tile but left and top collisions are offset by one tile.
To visually illustrate what is happening i took the print out and spawned the godot icon over the tile i was trying to get the data from, like this:
var dot_scene = preload("res://dot.tscn")
var surface_type : int
if collision_collider is TileMap:
var tilemap = collision_collider as TileMap
var collision_point = collision_info.get_position()
# Convert collision point to local coordinates of the tilemap
var local_point = tilemap.to_local(collision_point)
# Get the tile coordinates from the local point
var tile_coords = tilemap.local_to_map(local_point)
# Access the custom data from the TileSe
var data = tile_map.get_cell_tile_data(0, tile_coords)
# DEBUG Test which tile is being collided with
var dot_instance = dot_scene.instantiate()
var world_position = tilemap.map_to_local(tile_coords)
dot_instance.position = world_position
get_parent().add_child(dot_instance)
And sure enough, you can see when you hit any tiles below or to the right (well, you can’t see to the right but trust me when i say the result is correct!) the icon is spawned on the actual tile, whereas the ones to the left and above are offset by one tile.
The angular tiles do actually throw me off a bit because they all seem to be fine even though they are to the left and / or above!
I’m really struggling to work out a good way to fix this! An offset seemed like a good idea but as it is very much direction dependant that felt like a bit of a hack?