How to get the scene node from tilemap coords in godot 4

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By nake

Hello!

I’m quite new to the engine and I got stuck with the tilemaps in godot 4.

Long story short: I want to get the node of a placed tile by its coords to be able to change some properties from gdscript. However, that tile is an scene instead of a normal tile, so I did not place it myself and the name in the tree is auto-generated.

I can check the scene node tree during gameplay and confirm that each node exists there, so my guess is that there is some kind of tilemap → node list somewhere. However, maybe it is not directly exposed to the user?
I noticed in the engine source code that there is a function that might do what I want, but it is not exposed (in scene/2d/tile_map.h):

// Not exposed to users
TileMapCell get_cell(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const;

I’m not sure if there is a way to access that node somehow that I am not aware of (still really new to this), or maybe it is a feature not added yet (as this is a very new feature of tilemaps).

Any ideas?

For a more tangible example:
I’m making a top-down game (imagine hotline miami or darkwood top-down style).
The player is in a ship that I create with a tilemap. (normal tiles)
The ship has tiles that you can interact with. For example, doors. (scene tiles)

At startup, I want the ship script to change some data about the doors depending on their position in the ship. I have some logic that can give a list of doors to change but I am failing to get the door node given the cell coordinates.

I guess in the worst case scenario, I could just create the doors myself instead of using the tilemap, but with the new feature in godot 4 of being able to place scenes as tiles, I kinda feel there must be an easy way to do this. And I can also see others asking similar questions when godot 4 releases.

Thanks in advance!

:bust_in_silhouette: Reply From: capypaw

I faced this problem recently. I can’t find a way to directly map the node to the TileMap, but there’s set_cell() and get_cell_alternative_tile() method which enable us to set and get a custom data to a tile. This custom data can be the Node’s index which we can access with get_child method inside TileMap script.

Assuming that the TileMap node has children nodes, the way I use it in TileMap script is like this:

extends TileMap

func _ready():	
	for child in get_children():
		var child_coord: Vector2i = local_to_map(child.position)
	
		# Set child index to the grid's cell
		set_cell(0, child_coord, 0, Vector2i.ZERO, child.get_index())

func do_something(child_coord: Vector2i):
        # Get the node's index stored in the cell
        var child_index: int = get_cell_alternative_tile(0, child_coord)
	    var child_node: Node2D = get_child(child)

Ah, that’s clever! Thanks!

It’s a bit annoying that there is no way to access the link to the nodes, moreover because they seem to be actually saved in the tilemap class internally. As a workaround your solution seems easy to implement and effective, so thank you very much for sharing. I think I will try it out too.

nake | 2023-01-09 07:11