Godot Version
4.4
Question
My game requires me to update individual cells/tiles collisions if the map data gives the tile a different collision than the default defined in tileset, and for that I am using _tile_data_runtime_update.
What I have works visually (I can see the collision shape is applied correctly when running game in debug) but the player can’t collide with it. I have collision layer and masks enabled and they’re both on layer 1. Player has layer 1 and 4 enabled. Am I forgetting about something? Am I doing something wrong? I looked for a solution everywhere, but can’t find anything.
game_scene.gd:
for i in tiles.size():
var tile_data = tiles[i]
var x = i % Constants.map_width
var y = i / Constants.map_width
var cell_pos = Vector2i(x, y)
var source_id = get_or_create_tile_source(tile_data["id"])
var collision_id = int(tile_data["properties"][2])
var transform = get_tile_transform(tile_data["properties"])
# Set cell with transform
tilemap.set_cell(
cell_pos,
source_id,
Vector2i(0, 0), # Atlas coordinates (assuming tiles are at (0,0) in their source)
transform # Apply the transform
)
var tile_source = tilemap.tile_set.get_source(source_id)
if tile_source is TileSetAtlasSource:
# Get DEFAULT collision ID from source
var base_data = tile_source.get_tile_data(Vector2i(0, 0), 0)
var stored_id = base_data.get_custom_data("collision_id")
# Only override if different
if stored_id != collision_id:
set_specific_cell_collision(cell_pos, collision_id)
func set_specific_cell_collision(cell_pos: Vector2i, collision_id: int):
# Store collision override for specific cell
tilemap.custom_collisions[cell_pos] = collision_id
TileMapLayer.gd (Attached to TileMapLayer Node):
extends TileMapLayer
var parent_game: Node
# Stores cell-specific collision overrides {Vector2i: collision_id}
var custom_collisions := {}
func _use_tile_data_runtime_update(coords: Vector2i) -> bool:
return custom_collisions.has(coords)
func _tile_data_runtime_update(coords: Vector2i, tile_data: TileData) -> void:
var collision_id = custom_collisions.get(coords, -1)
# Clear existing collision polygons for PHYSICS LAYER 0 (editor's Layer 1)
tile_data.set_collision_polygons_count(0, 0)
# Apply new collision shape from the library
if collision_id in parent_game.collision_tiles:
var shape = parent_game.collision_tiles[collision_id]
if shape is Array: # Multiple polygons
tile_data.set_collision_polygons_count(0, shape.size())
for i in range(shape.size()):
tile_data.set_collision_polygon_points(0, i, shape[i])
else: # Single polygon
tile_data.set_collision_polygons_count(0, 1)
tile_data.set_collision_polygon_points(0, 0, shape)
Or maybe it’s a new bug?