godot: Area/Area2D doesn't detect static bodies if "Monitorable" is disabled (3D issue only when using GodotPhysics)
Godot version: 184b2fe
Issue description: This could also affect the 3D version of it, but I just tested in 2D.
If an Area2D’s Monitorable
property is disabled, it will fail to detect static bodies.
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 14
- Comments: 28 (23 by maintainers)
https://github.com/godotengine/godot/issues/17238#issuecomment-370192809 @Ranoller
Then how would you detect StaticBody2Ds ?
The GD4 Area3D documentation says:
3D area that detects CollisionObject3D nodes overlapping, entering, or exiting.
So yes, that is what we expect (and how it works in GD3/Bullet). If any PhysicsBody with an enabled CollisionShape and matching layer/mask enters an Area, we should get body entered signals. If any PhysicsBodies collide with other PhysicsBodies with matching parameters, they should collide and send signals.
We also understand that we should be using StaticBodies for immovable objects, RigidBodies for physics movable objects, Kinematic/Character bodies for user movable object, and Areas for detection.
If there’s a better way to do it, fine. Us users don’t care about or understand pairable or not pairable or the BVH or the other magic you guys are doing under the hood. We just expect the code to work as advertised in the documentation and tutorials, and provides the functionality we need (present in GD3/Bullet). Currently GD4 doesn’t quite do that and the documentation is inconsistent.
So… what is the best way of detecting static bodies? Like, let say I want a character to jump BEFORE running off a ledged, then I want some kind of detector running in front of them that says when there isn’t any ground. I don’t want the detector to have any physics in it (hence shouldn’t be a body), I want it to only be a zone of detection.
This seems like something that “area2d” should do, or at least, have the ability to do. If not, then, what type of object should have that behavior.
I’m all for fixing some other thing that is a bug, but … if you do I’m not sure how to implement the thing I’m imagining.
No. The problem arises even when
Area
s that aremonitoring
collide withStaticBodies
, or at least with tiles, in my case. Nothing is detected until yourArea
s havemonitorable
On, which doesn’t make sense, and that’s the bug, for what I’m able to understand.In other words, to solve the bug, either:
Area
hasmonitorable
On, but in this case you couldn’t detect tiles, so something would have to be done for making tiles detectable byArea
sOR
Area
should always detectStaticBodies
if theArea
has themonitoring
parameter On (not themonitorable
parameter).In my case I was trying to detect tiles from a TileMap. The documentation for
Area2D
says:body_entered(body: Node)
Emitted when a physics body enters. The body argument can either be a PhysicsBody2D or a TileMap instance (while TileMaps are not physics body themselves, they register their tiles with collision shapes as a virtual physics body).But it doesn’t work unless you switch “monitorable” on, on the detector, which makes no sense.
Saw a few people had been bumping this and similar bugs. Just to review some options for fixing this (as I remember, it’s been a while so my memory may be wonky) for the benefit of new physics contributors such as @rburing :
Imo there are two good options which solve the bug (and don’t necessarily adversely affect performance in the situation where this mode is not needed). Both involve the need for an extra flag on
Areas
, whether or not theArea
should collide test againstStatics
. Or alternatively the monitorable state could become more of an enum:The two ways obvious ways of implementing this:
collide all
is set, theArea
is added to the dynamic tree instead of the static tree. This would be more expensive than normal mode, but not as expensive as monitable because there is no reporting.collide all
Areas into this third tree instead of the static tree. This has the advantage that we could eliminateArea
toArea
collision checks.Just to emphasize that we made the BVH totally configurable with the templated trees in #55640 , so it is possible to add / remove trees / configure collision masks without changing the actual BVH code at all (and thus requires no specialist knowledge), and this can be done by a physics contributor as in the approach in #58505 .
I was looking how to detect static bodies with a non-physical colliders and ENABLING MONITORABLE in Area2D is the only way.
It shouldn’t even be called a bug since area2D isn’t monitorable anyway(except by others Area2D, I know, but it can be handled with collision_mask bits). So, if Area2D isn’t supposed to be detecting static bodies in any way, please let this “bug” continue
I am not knowledgeable enough about physics engine internals to comment on the technical merits of any choice, but as a user, the idea that ‘monitorable’ and ‘collide all’ are two options in the same enum feels weird, since ‘monitorable’ is about being detectable whereas ‘collide all’ is about detecting other bodies.
@barbaros83 I can confirm this is considered a bug. When it’s fixed, it will very likely be on both 4.x and 3.x.
No, it’s definitely a bug. It’s just not an easy one to fix, because of the way the physics engine was designed.
The problem is with the way the physics engine is designed. To make things efficient,
StaticBodies
are not checked if they’re colliding with anything, because they don’t move. Instead it relies on the otherCollisionObject
s moving and detecting collisions with it. Similarly, to make things efficient,Area
s that are notmonitorable
are not checked if they’re colliding with anything. The problem arises when movingArea
s that are notmonitorable
collide withStaticBodies
. Neither is checking for collisions, so nothing is detected.Just looking at fixing this now. Here is a minimum reprod project (there was another earlier but it didn’t work well for me.
Just run it using either Godot physics or Bullet, it prints the “Area entered” message with Bullet but not with Godot physics.
Lawn_StaticAreaCollision.zip
lol, i was going crazy thinking i did something wrong, turns out its a long standing bug. is this going to be fixed in 3.x ? 1 of the comments suggests its not a bug, but it definitely is, because the dev should decide what the node should do, not asuming anything. in my game i have a building that i can place, wich is a staticbody, and the enemy characters are kinematicbody’s, with an area for detection, it makes sense the way its set up, and the way you would asume it works, if detection is not desired there are many ways to handle that, put it on a diffrent layer, or disable the body, filter the bodies that enter the area.
Experiencing this in 3.2.3 stable. It’s confusing enough that it took me quite a while to understand what was going on in my project. In my case I was trying to detect tiles from a TileMap.
@Ranoller Well, then the bug is that is detecting static bodies when
Monitorable
is enabled then?