godotengine / godotengine/godot
`get_gravity` yields different results from `_process` and `_physics_process`
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
Reproducible in: Godot 4.3.dev [d3352813e]
### System information
Windows 10 (10.0.22631)
### Issue description
Related to #84640.
Due to the current implementation of `PhysicsBody*D.get_gravity` relying on `body_get_direct_state` you will end up with desync between the gravity reported by `_physics_process` and the gravity reported by `_process`, within the same physics frame.
This means that when a body enters/exits an area with some type of gravity override, `_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 logs when the `CharacterBody3D` enters the `Area3D`
- Note the output logs when the `CharacterBody3D` exits the `Area3D`
### Minimal reproduction project (MRP)
[GravityDesync.zip](https://github.com/godotengine/godot/files/14171687/GravityDesync.zip)
Contributor guide
Research direction
Start by running the attached GravityDesync.zip MRP and compare the values reported from _process and _physics_process when the CharacterBody3D enters and exits the Area3D. Trace PhysicsBody*D.get_gravity through body_get_direct_state and verify that both callbacks observe consistent gravity for the same physics frame; done means the reported values no longer desynchronize.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, godot
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100