Detect area_enter from areas created with the Physics2dServer

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Eric De Sedas

I’m trying to implement a similar logic to the one on the “Shower of Bullets” demo example , but with a couple of differences:

  • I’m using Godot 3.1, while that demo is made for Godot 2.1
  • Collisions are detected with areas instead of bodies

I have a bullet spawner that shoots bullets in random directions, and several areas instanced in the scene that are listening to their area_enter. I use the Physics2dServer to create and move the bullet areas.

The problem is that I can’t seem to detect any area_enter signal on my instanced areas, and I’m not sure if I’m missing something. Here is the implementation I used:

var circle_shape
var bullets

# The main bullet class that holds position information
class Bullet:
    var pos : Vector2 = Vector2()
    var movement_vector : Vector2
    var area : RID

# Create the base shape in the scene's _ready method
func _ready() -> void:
    circle_shape = Physics2DServer.circle_shape_create()
    Physics2DServer.shape_set_data(circle_shape, 8)

# Spawn bullet method inside the main scene
func spawn_bullet(initial_movement : Vector2) -> void:

    var bullet : Bullet =
    bullet.movement_vector = initial_movement

    var used_transform : Transform2D = Transform2D()
    used_transform.origin = bullet.pos

    var area_id : RID = Physics2DServer.area_create()
    Physics2DServer.area_set_space(area_id, get_world_2d().space)
    Physics2DServer.area_add_shape(area_id, circle_shape)
    Physics2DServer.area_set_transform(area_id, used_transform)
    Physics2DServer.area_set_monitorable(area_id, true)

    bullet.area = area_id


# Bullet movement logic
# Has a reference to the bullet array
func _process(delta: float) -> void:
    for bullet in bullets:
        var used_transform := Transform2D()
        bullet.pos += bullet.movement_vector.normalized() * 100 * delta
        used_transform.origin = bullet.pos
        Physics2DServer.area_set_transform(bullet.area, used_transform)


# Drawing logic
func _draw() -> void:
    var offset = image.get_size() / 2.0
    for bullet in bullets:
        draw_texture(image, bullet.pos - offset)

The bullets are drawn correctly, but no area_enter signal is ever called in any of my areas called.

Something I noticed (and I don’t know if it’s intended) is that when enabling Debug → Visible Collision Shapes on my project, all of my instanced areas are shown while none of the areas created by the Physics2dServer are visible.

I’m not sure if I’m missing an area parameter, or if the areas are being added to the tree at all since I cannot find a lot of documentation for this feature.

Something extra I just noticed:

Changing the _process method to this:

func _process(delta: float) -> void:
	for bullet in bullets:
		var offset : Vector2 = bullet.movement_vector.normalized() * 100 * delta
		bullet.pos += offset
		var used_transform = Transform2D(0, bullet.pos)
		Physics2DServer.area_set_transform(bullet.area, used_transform)

and listening to the area_shape_entered seems to detect the collision, but the area_id and area parameters are passed as 0 and null, respectively.

I’ve just found this issue, maybe it is related?

Eric De Sedas | 2019-03-20 21:22