I have a character (2D Sprite) and it has a collision shape. How would I via GDScript detect a collision between the tile collision shape and the character collision shape? I'm not using builtin physics. I just want to know if the Sprites collision shape has collided with the collision shape on the tile in the tilemap set.

This is using Godot 4 and I require a gdscript way of finding if a collision has occurd.

Thank you!

  • You probably want the CharacterBody to have the script and be the root of the scene, that way the sprite will move with it.

    That will also make move_and_collide work.

    You can also move the body with move_and_slide.

    As an example :

    # In _physics_process
    if move_and_slide(): # Character is colliding
        for i in get_slide_collision_count(): # Loop for every collision in this frame, in case there was more than 1 collision
            var collision := get_slide_collision(i)
            if collision.get_collider() is TileMap:
                print("collided with tilemap")

    CharacterBody is the kinematic body btw

If you're character is a characterBody2D then when you call move_and_collide() you can assign it to a variable like :

var Coll := move_and_collide(velocity)

Now the Coll variable has information about all the collisions with your character. Just read the docs about this function.

I get "Function "move_and_collide" not found in base self:

All that is attached to the character is a CHaracterBody2D and a CollisionShape2D. Do I need to mess with Kinematic bodies and all that physics stuff? I hope not.

I'm using Godot 4

Can you post a screenshot of your character's scene tree?

  • Amon replied to this.

    You probably want the CharacterBody to have the script and be the root of the scene, that way the sprite will move with it.

    That will also make move_and_collide work.

    You can also move the body with move_and_slide.

    As an example :

    # In _physics_process
    if move_and_slide(): # Character is colliding
        for i in get_slide_collision_count(): # Loop for every collision in this frame, in case there was more than 1 collision
            var collision := get_slide_collision(i)
            if collision.get_collider() is TileMap:
                print("collided with tilemap")

    CharacterBody is the kinematic body btw

    • Amon replied to this.

      spacecloud Hey, One last question if you don't mind. How would I grab the tile that was collided with into a variable to access its position data?

        Amon
        This horrifying one liner can get the tile's data :

        var tile_data : TileData = collision.get_collider().get_cell_tile_data(0, collision.get_collider().local_to_map(collision.get_collider().to_local(collision.get_position() - collision.get_normal())))

        This part :

        collision.get_collider().local_to_map(collision.get_collider().to_local(collision.get_position() - collision.get_normal()))

        Gets the tile's position in the tilemap by subtracting the collision's normal from it's position to make sure the position is inside the right tile, then converting that to the tilemap's local space, and finally converting that local position to the tile's cell coordinates.

        • Amon replied to this.

          spacecloud I'd just like to say that in other languages this would have been a simple one liner but in Godot it looks absolutely mad. I hope the rest of godot is not like this because if the Godot devs think something like this would be simple for newcomers then they are mistaken.