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

get_contact_count yields different results from _process and _physics_process #88018

Closed
mihe opened this issue Feb 6, 2024 · 1 comment · Fixed by #88019
Closed

get_contact_count yields different results from _process and _physics_process #88018

mihe opened this issue Feb 6, 2024 · 1 comment · Fixed by #88019

Comments

@mihe
Copy link
Contributor

mihe commented Feb 6, 2024

Tested versions

Reproducible in: 4.3.dev [d335281]

System information

Windows 11 (10.0.22631)

Issue description

This is essentially the same problem as #87996, but for a different method.

Due to the current implementation of RigidBody*D.get_contact_count relying on body_get_direct_state you will end up with desync between the contact count reported by _physics_process and the contact count reported by _process, within the same physics frame.

This means that when a RigidBody*D makes contact with something, _process will pick up on the change before _physics_process does, while they still report the same position in the world, which can potentially lead to subtle and hard-to-track-down bugs.

The reason for this is because of how a frame is laid out in Godot, which in very simplified terms goes something like this:

  • Maybe do the physics tick
    • Pull state from the physics server
    • Run _physics_process
    • Step the physics simulation/server
    • Maybe repeat
  • Do the idle tick
    • Run _process
  • Render, audio, input, etc.

The important thing to note here is that the physics simulation/server is stepped inbetween _physics_process and _process, which means that the physics simulation/server is always one tick ahead of _physics_process while _process is running.

This means that if you use something like body_get_direct_state, which as the name would suggest gives you direct access to the physics server, you will bypass the state synchronization that typically happens before _physics_process and access the most current (future) value in the physics simulation/server instead, leading to a desync with _physics_process.

Steps to reproduce

  • Run the MRP
  • Note the output log when the body hits the floor

Minimal reproduction project (MRP)

ContactCountDesync.zip

@smix8
Copy link
Contributor

smix8 commented Feb 6, 2024

While I think caching is a decent solution for the immediate problem accessing physics direct states in process outside of physics_process is close to an error. I know a lot of nodes and things treat it as an error but not everything has the "error check" implemented.

The issue is imo more systemic in that the physics has no working callback system so users can not set their physics updates in scripts and also do something with the result after the sync, all in the same "script" frame. They regularly need to make work with 1 frame outdated physics infos in their scripts.

I know navigation had to add its own callback system so the physics step avoidance velocity could get back to the user in scripts to actually do something with it after the velocity was set and calculated, instead of being 1 frame/step completely outdated all the time.

@akien-mga akien-mga modified the milestones: 4.x, 4.3 Feb 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants