1
\$\begingroup\$

My player is a KinematicBody2D with a CollisionShape2D as a child.

When the player presses a button I want to check if he stands on certain (static) areas.

This areas are Area2D with a CollisionShape2D as a child.

so I thought, i could do something like this in my player-class:

public override void _Process(float delta)
{
    

    if (Input.IsActionPressed("interact"))
    {
        //Check which areas are overlapping
    }
    
    //Do other stuff like moving
}

But unfortunately I did not find a way to do this with KinematicBody2D.

So is there a way to query which Area2D's are overlapping with my KinematicBody2D?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

This is much easier starting with the Area2Ds. You can query each Area2D with overlaps_body. Something like this:

var areas := [$Area, $Area2] # perhaps get the list from somewhere else
for area in areas:
    if area.overlaps_body(self):
        print("Overlapping " + area.name)

On the other hand, if you don't have references to the areas, you will have to do a physics query, which I believe would be like this:

var space := get_world_2d().direct_space_state
var query := Physics2DShapeQueryParameters.new()
query.collide_with_areas = true
query.collide_with_bodies = false
query.set_shape($CollisionShape2D.shape)
query.transform = $CollisionShape2D.global_transform
var result := space.intersect_shape(query)
for area_collision in result:
    var area := area_collision.collider as Area2D
    if is_instance_valid(area): #perhaps some other checks here
        print("Overlapping " + area.name)

This is the physic query in C#:

        var space = GetWorld2d().DirectSpaceState;
        var query = new Physics2DShapeQueryParameters();
        query.CollideWithAreas = true;
        query.CollideWithBodies = false;
        var collision = GetNode<CollisionShape2D>("CollisionShape2D");
        query.SetShape(collision.Shape);
        query.Transform = collision.GlobalTransform;
        var result = space.IntersectShape(query);
        foreach (Godot.Collections.Dictionary item in result)
        {
            GD.Print("All Dictionary: " + item.ToString());
            var collider = item["collider"];
            GD.Print("Found: " + collider.ToString());
            GD.Print("Type: " + collider.GetType().ToString());
            var area = collider as Area2D;
            if (area!= null)
            {
                GD.Print("Some Random Area");
            }

            var treasure = collider as Treasure;
            if (treasure != null)
            {
                GD.Print("Found some treasure");
            }
        }
\$\endgroup\$
2
  • \$\begingroup\$ Thanks a lot. I found this to be quite complicated but it works fine. I added the C# Code I use to your answer. \$\endgroup\$
    – Gener4tor
    Commented Nov 25, 2022 at 23:37
  • \$\begingroup\$ @Gener4tor I did overlook it was C#, I'll add the tag to the question. Edit: done. Edit2: You might still want to use Object.IsInstanceValid (is_instance_valid). \$\endgroup\$
    – Theraot
    Commented Nov 26, 2022 at 0:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .