Open pmoosi opened 3 months ago
To interact, Areas need to be able to scan each-other.
SomeArea layer=0 SomeArea mask=1. Can scan layer1. Scans SomeOtherArea and SomeBody.
SomeOtherArea layer=1 SomeOtherArea mask=0. Can't scan anything.
SomeArea layer=1 SomeArea mask=1. Can scan layer1. Scans SomeOtherArea and SomeBody.
SomeOtherArea layer=1 SomeOtherArea mask=1. Can scan layer1. Scans SomeArea and SomeBody.
I'm not sure I understand. I'm only talking about the events of SomeArea
SomeArea layer=0 SomeArea mask=1. Can scan layer1. Scans SomeOtherArea and SomeBody.
So, as I understand it, SomeArea should emit the area_entered event when the collision layer of SomeOtherArea is changed.
Or are you saying that both areas need to scan for each other so that one emits the event? I don't think that's the case. When I set the collision layer when they are not overlapping and only then move SomeOtherArea inside SomeArea the event is emitted. The same is also true when I set the layer directly in the editor (or in _ready), not after some delay in the script. Also it's emitted for the body which has the same layer/mask setup.
Physics server only tries to collide objects that have moved so it's better to keep masks and layers consistent.
But, looking at the source, a layer change does count as having moved so, let's see. Two tests:
Does it happen because one is inactive?
SomeOtherArea.collision_layer = 1
SomeArea.collision_mask = SomeArea.collision_mask # poke!
Could it be a timing problem?
var p := false
func _ready():
# await timeout
p = true
func _physics_process(_delta):
if p:
# set layers
Can't do it myself right now but feel free.
Physics server only tries to collide objects that have moved so it's better to keep masks and layers consistent.
Good to know. Maybe this should be mentioned somewhere in the documentation (if it's not fixed)? The thing is that it is inconsistent between body_entered and area_entered and Godot 3 and 4 which might lead to confusion - at least it did for me.
I tried both tests and neither emitted the signal.
If both tests failed, only possibility (that I can imagine) is that the areas are already considered to be overlapping and it'll only signal area_exit.
Ok, so I played around with it a little bit more and I found that when I 'poke' twice it triggers the signal. Interestingly, the first does not have to happen close to the changing of the layer.
So this works:
func _ready():
# await timeout
# set layers
SomeArea.collision_mask = SomeArea.collision_mask # poke!
SomeArea.collision_mask = SomeArea.collision_mask # poke again!
And this:
func _ready():
SomeArea.collision_mask = SomeArea.collision_mask # poke!
# await timeout
# set layers
SomeArea.collision_mask = SomeArea.collision_mask # poke again!
Okay, two pokes work. Does the connection timing make a difference to the poke? Like if it's connected through the node panel in the inspector instead of code, does it differ?
Nope, connecting through the inspector does not change anything.
Tested versions
System information
Godot v4.3.beta.mono (e09a3e931) - Ubuntu 22.04.4 LTS 22.04 - Wayland - Vulkan (Forward+) - integrated AMD Unknown (RADV RENOIR) - AMD Ryzen 7 5800H with Radeon Graphics (16 Threads)
Issue description
I have a scene with two Area2Ds that are overlapping. The collision layers and masks are set to not trigger any collisions. When I now set one area's collision layer to the collision mask of the other area, no area_entered signal is emitted. This only applies to intersecting areas. If the layer of an intersecting body is updated, the body_entered signal is emitted.
I'm not sure if this is intended behavior or a bug. I found some similar older issues that were fixed by #39894. In Godot 3.5.3, the signals are emitted.
Steps to reproduce
The MRP contains an Area2D with collision mask '1'. A CharacterBody2D and another Area2D that overlap the first area have collision layer '0'. A script connects the body and area entered signals for which it prints a short message ('Body/Area entered'). It then sets the collision layers of the body and the second area to '1' after 1s delay. Only the message for the body entered signal is printed.
Minimal reproduction project (MRP)
mrp.zip