0 votes

This is a fairly common question both here and in other places like Reddit. But I am a bit stuck as the commonly proposed solution does not seem to work for me.

When a KinematicBody2D collides with a tile in a TileMap, I want to get that tile's id. Here is how I am doing this:

extends KinematicBody2D

var velocity = Vector2.ZERO

func _physics_process(_delta):
    velocity.x = 0
    velocity.y = 100

    if Input.is_action_pressed("ui_left"):
        velocity.x = -60

    if Input.is_action_pressed("ui_right"):
        velocity.x = 60

    velocity = move_and_slide(velocity, Vector2.UP)

    for i in range(get_slide_count()):
        var collision = get_slide_collision(i)

        if collision.collider is TileMap:
            var cell = collision.collider.world_to_map(collision.position - collision.normal)
            var tileId = collision.collider.get_cellv(cell)
            print("tileId ", tileId)

The commonly proposed solutions seems to rely on tilemap.world_to_map(collision.position - collision.normal)

But I am finding this only works if the collision occurs on the left side of the tile. If it occurs on the right half, I end up with -1 as the tile id.

I made a tiny Godot project that shows the issue I am having:


If you run that project, then hold down the left arrow key, you'll see in the output console the tile id go from -1 to 0. I am expecting it to always be 0.

The above code is from this project. My actual project has more complex code, but ultimately seems to have the same problem.

Can anyone tell me what I am doing wrong?

I am using Godot 3.2.2.stable

in Engine by (84 points)

I've created a pull request in your github with demonstration of my answer below.

1 Answer

0 votes

Main issue with your way is that the get_cellv doesn't do what you think it does. It returns the index of the sprite in the tileset. Not an index of the tile in tilemap.

Plus: Be aware that you won't get multiple slide detections with one tilemap (demonstrated by creating multiple tiles and collide markers).

by (200 points)

The index of the sprite in the tileset is what I am interested in. I want to know what type of tile has been touched. We discussed this already in the PR (thanks again). But it looks like what I want to do might not be possible, so I am exploring other options.

Basically what happens is Godot will tell me there has been a collision with the tilemap, but world_to_map(collision.position) does not return the correct tile coordinate in all circumstances. A collision with the tile at (3, 1) happens, but world_to_map(collision.position) returns (4, 1) if the collision happens to the far right side of the tile.

I wonder if I should submit a github issue for this? I am very new to Godot, so I have a lot to learn. But this feels like it might be a bug?

I think the solution is to just subtract Vector2(1, 0) from collision.position. This seems to work because Godot seems to bias the collision towards the right side of the kinematic body.

Thanks to njamster for the idea. He mentioned it in this thread which is also about kinematic bodies and tilemaps: https://godotengine.org/qa/61590/how-would-i-detect-a-collition-on-a-specific-tile-type

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.