How do you make tiles interactive in Godot?

Godot Version


I have been trying for quite some time, to make my tiles interactable, so that if I (player) stay on them and give Input, then I want to get Output in the debugger.
But I have not found any way to achieve it, at all. The selected tile should be the one.

I have no Idea how to do it, even after looking up videos and looking for answers online. Here is my code:

I just don’t know what to do anymore. Any answer is appreciated, even if it isn’t the most efficient way to work around the issue. The main thing I hope to find is a generic way of being able to interact with the tilemap on a certain tile.

Thank you for reading

1 Like

I basically never do 2D, but some points/questions below:

First, can you share screenshots of the other scenes?

Second, are you intentionally hardcoding coords to be Vector2(1,1) as this would return the same result every time (i.e it would print nothing). I would personally put the check_interaction() function on whatever character controller I am writing and pass it the coords from the character’s position (relative to the tilemap).

Third, why is the TileMap a child of an area node?

Like, your trying to do this?


Could you show us the result of print(tile_id) ?

1 Like

I would also ask, why is interactive_tile = 5? What’s special for it to be 5/what’s 5?

I have tested the code line:

tilemapvar.get_cell_atlas_coords(0, roomMap.local_to_map(mousePos))

and it works as expected (just being thorough).

I’m guessing there are some misunderstandings in there that need to be clarified.

Relying on the atlas coordinates for custom data might not be a good idea. If you want to make other tiles interactive, you will need to add again the coordinates somewhere and that won’t scale up.

I had to deal with your use case, and I have a better solution for you !

You could try to assign custom data to your TileSet’s tiles. Take a look at this part of the TileSet official documentation :

You could try the followings :

  • In the TileSet inspector (right of the editor window when you are inspecting the TileMap node, or the TileSet resource), add a custom data layer named “interactive” and set its type to bool
  • Go to the TileSet editor (you have it opened at the bottom on your screenshot) and go to the “Paint” section (“Zeichnen” in your language)
  • Select your custom data (“interactive”) in the “Paint Properties”, set it to true , and paint the tiles that you want to be interactive

Now for the scripting part :

  • Get the tile data with var tile_data := tilemap.get_cell_tile_data(0, your_tile_coords). It will return a TileData (see doc here)
  • For safety, you could check if get_cell_tile_data returned null : that can happen if the cell doesn’t exist
  • Check if the tile is interactive by using tile_data.get_custom_data("interactive") : if all goes well, you should be done

Alright, thank you sooo much for your reply. I will look into it more once I am home, to see if I can get it working. If not, then I will comment again on this topic.
Again, thank you so much

I will explain once I’m home, since I am quite tight on time currently. Thank you for your reply though, it is really appreciated.

I added the 5 to check if the program sses that it is in the 5th row. Sinde the atlas coordinates are (5,3) it should print the statement. But even then I was met with heavy inconsistencies. You are most definitely correct, there is a huge misunderstanding in the code, I just don’t really know where. But now there are some approaches I can take thanks to the comments here.

Hello again, I am currently trying to implement your solution, but ti seems like I ran into a code problem again.
The code:

sorry, but I just really don’t know what is going on. I read your message and added the necessary parts you mentioned.
1.The costum data layer is added (“is_interactive”)
2. The wanted tile is selected
3.the coords of the tile (atlascoords are added)

The full error message:
Cannot infer the type of “tile_data” variable because the value doesn’t have a set type.

Is there maybe a stupid mistake I made?

The tilemap:

I hope this somewhat makes it easier to identify the issue.

For your interest, the “:=” operand means “assign the value and try to infer the type of the value” (“infer” meaning “guess”)

I’m not sure why you have this script error but you can try :

  • using “=” instead of “:=”
  • move the assignment of tile_data elsewhere, like _ready() or _process(_delta) because with your script, there is a huge risk that the tile_data will try to get the value BEFORE the execution of @onready var tilemap = $TileMap
1 Like

Awesome news my friend!
It seems like this worked!
I also added some logic to see if the custom_data is in fact “is_interactive” and it worked.

As you can see, the print statement works, so the data_type gets assigned perfectly fine!
Thank you so mch for the ambigious help, now that I understand how you can do it, I am pretty sure that it will be a lot easier to implement with more logic.

Thank you so much and have an awesome day =)

1 Like

Awesome :grinning:

You can go crazy and I think you can put any kind of data in the tiles, not only “simple” bool flags !

Maybe flag my longer message as a solution (this one), so that next people can find the solution more easily

Unfortunately I still struggle a bit with the addition of logic to tge script, however, I think it will be manageable.
I guees we will see…once I find a way to set the player coords into tile-coords, this should be fairly simple.

I struggled with the exact same issues in a recent game jam haha

You can use this function to go from some global position, to tile coordinates :

func get_tile_coords_from_global_position(some_global_position : Vector2) -> Vector2i:
	return tilemap.local_to_map(tilemap.to_local(some_global_position))

Pretty sure it’s because custom_data can be ANYTHING, thus the error.

I would also suggest to cast the answer to the specific of the custom_data.


var title_data := tilemap.get_cell_tile_data(0, Vector2i(5, 3)) as SomeTypeOfData

That way, you ensure the type is proper.

I will try that later and send the results in, looks good though :slight_smile:

Oh man, this might be just a little too comlicated for me.

In the code, I tried to make the print statement run, if I am at the spot and the tile data is the same as my player coord. Sorry, but could you please tell me what I am doing wrong here?I don’t know any other way to compare the two or to check if they are currently interacting with each other.
Again, sorry for the stupid questions haha

if tile_data.get_custom_data("is_interactive")== some_global_position:

assuming your is_interactive layer has the value of Vector2 position, it should work

but this will need you to check if there even custom data value of this tile_data. because im pretty sure only a few tile in tileset has the custom data of “is_interactive” layer

i just see your previous screenshot of the is_interactive, it’s a value type of boolean. i dont see this is getting somewhere now

Hm, I see.
Unfortunate. I guess there is still another way to do it though.