Marko Taht
Marko Taht

Reputation: 1526

Godot 4.1 How to detect what tile did rigidbody2d collide with?

I have a special tile in the tilemap, that when colliding with player needs to do a special behviour. Since i cant add anything specila to the tile, the logic needs to be set up on the player side. But i cant seem to figure out how to find what tile the player is colliding with. All existing tutorials are for Godot 3.x where Tilemap collision system is different than in 4.1.

Does anybody know how to get the tile player is colliding with in godot 4.1? Also im using C# as the scripting language.

Upvotes: 0

Views: 2141

Answers (2)

hsandt
hsandt

Reputation: 760

So I found a way to get the last hit tile data, if you know the tile layer you expect the tile to be on.

The key is to use Tilemap.get_coords_for_body_rid(KinematicCollision2D.get_collider_rid())

Below is a full example to detect whether the tile has a polygon collision set on a certain physics layer with one-way physics.

This is probably a bad example, since one-way platforms really make sense when below the character, so in my own game I actually check them with a downward Raycast on some OneWayPlatform physics layer (which is much easier). Whereas move_and_slide could hit a wall, ceiling, or sometimes nothing. But you can adapt the example to suit your needs.

var last_slide_collision := get_last_slide_collision()
if last_slide_collision:
    var last_collider := last_slide_collision.get_collider()
    var tilemap := last_collider as TileMap
    if tilemap:
        var tile_layer := 0 # set it to the tile layer containing your special tile
        var physics_layer_id := 1 # set it to the physics layer ID used by your special tile
        var polygon_index := 0 # in general there is only one polygon so 0 is good, but you can adapt
        var tile_collider_rid := last_slide_collision.get_collider_rid()
        var tile_coords := tilemap.get_coords_for_body_rid(tile_collider_rid)
        var tile_data := tilemap.get_cell_tile_data(tile_layer, tile_coords)
        var is_one_way := tile_data.is_collision_polygon_one_way(physics_layer_id, polygon_index)
        print(is_one_way) # do something here...

Upvotes: 0

Ilya
Ilya

Reputation: 1399

Prerequisites: I assume you work in 2D and have Sprite2D colliding with a tile in TileMap.

The short answer is:

Use Area2D as phisics body and subscribe to body_entered signal, it receives colliding object as an argument.

The long answer is:

To make collision happen and be able to detect with which object you've collided you need to add Area2D node to your Sprite2D and add shape (object inherits from Shape2D) as child to Area2D. Now you need to add colliders to your tiles, first select TileMap, and click "add physics layer" (it was something like that) in Inspector. Then, in bottom tab, select TileSet, select a tile and you'll see that physics layer properties are now added. You will need to draw or select all of it.

Here is an image that might clarify the TileSet part.

Soooo, now you have colliders in place. All you need to do now is to subscribe to 'body_entered' signal of Area2D node, and you'll get the colliding object as an argument to the handler.

Upvotes: 1

Related Questions