observer-patterngodotgdscriptgodot4

In Godot 4.1.1, signal from Area2d that detects if a RigidBody2D, that is inside that Area2d, is leaving, but not completely left yet


In a scene that has a RigidBody2D inside an Area2D, I want to detect the moment that the RigidBody2D have some portion out of the said Area2D.

I now that the Area2D has two signals with a body as a parameter:

I would like a signal that signals the change from "all part of the body is inside" to "some of the body is out".

Is there a way to make that signal? Or a good way to automatically create a new Area2D that borders the first Area2D?

RigidBody2D leaving Area2D with print on signals


Solution

  • There isn't an API for partial overlap.

    Creating a second area is the approach I've taken in the past.

    Doing it automatically means, from code, creating a new Area2D, setting any relevant properties and adding it to the scene tree, for example:

    var border_area := Area2D.new()
    border_area.collision_mask = collision_mask
    add_child(border_area)
    

    And you have to do the same for the collision objects, for example:

    var border_area := Area2D.new()
    border_area.collision_mask = collision_mask
    add_child(border_area)
    var collision := CollisionShape2D.new()
    collision.shape = $CollisionShape2D.shape
    border_area.add_child(collision)
    

    Except, of course, those should be scaled (here I'm assuming we are using a smaller collision shape so we can detect what is fully inside):

    var border_area := Area2D.new()
    border_area.collision_mask = collision_mask
    add_child(border_area)
    var collision := CollisionShape2D.new()
    collision.shape = $CollisionShape2D.shape
    collision.scale = Vector2(0.8, 0.8)
    border_area.add_child(collision)
    

    Alternatively you could duplicate the shape and change its size (which is different depending on which type the shape is).

    In either case, I believe the tricky part if figuring out the correct scale/size to use.


    Of course, that goes out of the window if the size of the other objects is not constant, as we would not be able to specify a margin that is correct for all of them.

    In particular, consider that if the other object is bigger than the area, it will never be fully inside.

    This suggest that it might be better to create an area bigger than the original, but leaving a hole cutout where the original is. So we can consider an object to be fully inside the area, if it is inside of it, but outside this new border area.

    Yet, creating the collision for this border area is not trivial... We would need to use a collision polygon, and that also means approximating the hole for shapes such as the circle or the capsule.

    Perhaps this is useful as reference: Godot-CollisionPolygonShape. It has code to generate the common collision shapes as polygons. And we can operate on them using Geometry2D, so we could make the cutout we want.