Skip to content
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

Stop reporting contacts for sleeping bodies when using Jolt Physics (reverted) #100533

Merged
merged 1 commit into from
Dec 17, 2024

Conversation

mihe
Copy link
Contributor

@mihe mihe commented Dec 17, 2024

Fixes #100515.

It seems that Jolt's contact listener can end up reporting contacts for bodies only to later in the simulation step decide that the body is inactive/sleeping. This meant that we ended up hanging on to the contacts for the first physics frame of sleeping, and since we don't call the state synchronization callback after that first sleeping physics frame we'd get stale values cached in the RigidBody3D node, leading to the issue seen in #100515.

This PR resolves this by checking to see whether the body did in fact end up sleeping once we flush the accumulated contacts in JoltContactListener3D::_flush_contacts(), which prevents sleeping bodies from reporting contacts at all.

Note that this does differ a bit from how things behave in Godot Physics, as Godot Physics seems to report (stale?) contacts for sleeping bodies, but since Jolt won't call the contact listener callbacks for sleeping bodies we don't have much of a choice, and frankly I don't think anyone would expect (or even want) contacts to be reported for sleeping bodies anyway.

@akien-mga akien-mga merged commit 6e2cf2a into godotengine:master Dec 17, 2024
20 checks passed
@akien-mga
Copy link
Member

Thanks!

@mihe mihe deleted the jolt/sleeping-contacts branch December 17, 2024 23:42
@NatGazer
Copy link

Thanks @mihe for the fast fix. But let me leave here my thoughts:

  • I believe Jolt integration should avoid breaking compatibility, if sleeping bodies wont report contacts, that will be a different behavior compared to the default physics engine

  • I truly think that the fact of a body being asleep or not should have anything to do with contact reporting. This can lead to unpredictable behavior for the user. Sleeping is an optimization, checking contact should always return the contact if the object is indeed in contact with something

Example: Let's assume you have a player that only jumps if no contacts are reported, and for some reason it is stopped and hanging in a rope. It enters sleep mode. Suddenly the player can jump. This can lead to all sort of bugs in games. I hope it's easy to cache the contact points before sleeping and make the engine return them even in sleep mode as the default physics engine did!

@mihe
Copy link
Contributor Author

mihe commented Dec 18, 2024

I appreciate the feedback, @NatGazer, and I can certainly see the argument for wanting contacts to be reported even when sleeping.

I am somewhat torn on what to do. The current behavior of Godot Physics could arguably be considered buggy to begin with, as the contacts that it persists after the body has gone to sleep are in fact stale.

For example, if you have a RigidBody3D that lands on top of a StaticBody3D, and the RigidBody3D subsequently reports a non-zero contact count, and you wait for that RigidBody3D to fall asleep, and then queue_free() the StaticBody3D, you will (with Godot Physics) find that the RigidBody3D sleeps/hovers mid-air while still (incorrectly) reporting a non-zero contact count.

(This is a bit of a contrived example, I'll admit, but the same thing can happen with sleeping bodies resting against eachother in general.)

It might be possible to emulate the behavior of Godot Physics with Jolt, by just ignoring all of Jolt's contact callbacks for sleeping bodies, but the question is whether we would actually want to.

Looking at Bullet in Godot 3, it seems that Bullet does in fact update its list of contact manifolds even for sleeping bodies, so while you do still get the behavior of the RigidBody hovering/sleeping mid-air, the contact count is updated continuously. I'm guessing that this somewhat defeats the purpose of having bodies be sleeping though.

@NatGazer
Copy link

For example, if you have a RigidBody3D that lands on top of a StaticBody3D, and the RigidBody3D subsequently reports a non-zero contact count, and you wait for that RigidBody3D to fall asleep, and then queue_free() the StaticBody3D, you will (with Godot Physics) find that the RigidBody3D sleeps/hovers mid-air while still (incorrectly) reporting a non-zero contact count.

Well, but the object staying mid air happens both on Godot Physics and Jolt Physics. This is another issue.

Looking at Bullet in Godot 3, it seems that Bullet does in fact update its list of contact manifolds even for sleeping bodies, so while you do still get the behavior of the RigidBody hovering/sleeping mid-air, the contact count is updated continuously. I'm guessing that this somewhat defeats the purpose of having bodies be sleeping though.

Yes, we should avoid this. A sleeping body should have minimal logic. But I believe it should cache the previous collision points and return them if requested anyway. Otherwise, if any implementation requires the user to have constant feedback on contact points, he will be forced to make the rigid-body never sleep, or to cache the last contact points reported before sleep.

I don't know who worked in Godot Physics at the time, maybe someone can have a word about this. I just think it will be very confusing to the user see the object stopped reporting contacts just because it is not moving. Specially for those not aware rigid bodies enter sleep mode.

@mihe
Copy link
Contributor Author

mihe commented Dec 21, 2024

I've put up another pull request (#100701) which effectively reverts this one, and instead does exactly what Godot Physics does, which is to only clear the list of contacts while a body is awake. The issue of potentially stale contacts seems like the lesser evil in this case, and the argument for compatibility with Godot Physics is undoubtedly a strong one either way.

I also realized there was a "regression" introduced by this PR for contact reporting with RigidBody3D frozen as kinematic, which this new PR happens to also address: #100700

@akien-mga akien-mga changed the title Stop reporting contacts for sleeping bodies when using Jolt Physics Stop reporting contacts for sleeping bodies when using Jolt Physics (reverted) Jan 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Jolt Physics: state.get_contact_collider_position() Fails for Sleeping Bodies Despite get_contact_count() > 0
3 participants