-
-
Notifications
You must be signed in to change notification settings - Fork 21k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Area2D body_entered signal is emitted too late #86199
Comments
I noticed that if you increase "physics/common/physics_ticks_per_second" or set "application/run/max_fps" to a low value so there are multiple consecutive _physics_process calls with no _process call in between, the overlap is not visible. The visual overlap only happens if there are _process calls between the _physics_process calls. I guess that's because the engine drawing happens somewhere during _process calls, as it's tied to FPS. |
Adjusting the fps will make it look like there is no overlap. But it will still overlap two physics frames (you will get two different positions where
Ideally it might be:
|
The reason for the two-frame overlap seems to be that
The following is an approximate process. Lines 3748 to 3750 in 2d0ee20
Line 3771 in 2d0ee20
Although |
@Rindbee Got any news on this? Just for the record, recently tried to replicate this on Unity with Unity's Area2D body_entered equivalent, OnTriggerEnter2D (which calls Destroy() to remove the Coin). On Unity it works as expected, without overlapping frames, with any framerate and timestep settings. As soon as the Player touches the Coin, OnTriggerEnter2D event is called immediately. You will never see the Player overlapping the Coin. But it seems impossible to replicate that behaviour in Godot. In Godot, the _body_entered signal may be called up to 2 visible frames late (depending on if you used move_and_slide(), 2 frames late, or updated position manually, 1 frame late), causing visible overlaps. I wish it worked the same way as in Unity. It seems there's no simple solution to this problem in Godot, at least not without relying on a custom coded solution or RayCasts that would add unnecesary performance overhead. Sadly nobody seems to care about this. It's probably such a small detail that most people won't notice. But then we have threads like these, all originated by the same issue: I only wish that someday this issue will be addressed and we can have events that fire on the same visible frame. Please don't let this issue die! Thanks |
I am facing similar issues in my project too, and sadly in my case the problem is not limited to a single frame. I too am unable to access the correct position of a RigidBody2D right after entering an Area2D. I want to use this position (and a stored previous position) to draw a line showing where the body has crossed the boundary of the area. Since the signal is fired late, both the current and the previous positions are already inside the Area2D, causing the line to be drawn in the wrong location. The line remains visible for way more than one frame, and it is clearly noticeable that it does not cross the boundary. At the moment, the only clean solution I found is to avoid using signals altogether and test for collisions manually in _physics_process, which does not seem ideal. |
Tested versions
Reproducible in: v4.2.1.stable.official [b09f793]
System information
Windows 10 - v4.2.1.stable.official [b09f793]
Issue description
Area2D body_entered signal seem to execute the callback 1 physics tick too late. Here is a visual representation, where the player is a CharacterBody2D, and the coin is an Area2D. The Area2D callback is set to increase the score by 1 and make the coin invisible and queue_free()
This visual overlap is undesired, the Area2D (coin) is set to become invisible (visible = false) in the body_entered callback, however it is still visible for the first frame where it overlaps with the player.
This also happens in the official pong demo, where the ball can be seen overlap the paddles if the speed of the ball increases.
If maybe this is not considered a bug and it's just the way the engine was designed, there should be an easy alternative to make an Area2D with immediate body_entered callbacks. There's a running thread on the forums on this issue: https://forum.godotengine.org/t/why-are-area2d-collisions-triggered-1-frame-late/37354
Steps to reproduce
Create a CharacterBody2D and another Area2D. Make the Area2D emit the body_entered signal, and on the callback set it so the Area2D becomes invisible or whatever. You'll see that the CharacterBody2D actually overlaps the Area2D for 1 frame.
Minimal reproduction project (MRP)
MRCollisionExample.zip
In this MRP just press right arrow key to move the CharacterBody2D to the right. When it reaches the Area2D, the callback is set to teleport the CharacterBody2D back to the start, however, they can be seen overlapping for a frame, like this:
This also happens in the Godot pong official demo: https://godotengine.org/asset-library/asset/121
If you increase the ball speed, it will be seen overlaping the paddles, which is a highly undesired visual glitch.
The text was updated successfully, but these errors were encountered: