godotengine / godotengine/godot

`get_gravity` yields different results from `_process` and `_physics_process`

Open
#87,996 2 comments 0 reactions 0 assignees View on GitHub
bug discussion topic:physics
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.