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

[Bullet] 3d physics stepping is two frames late for bullet physics #37702

Open
Tracked by #45022
huhund opened this issue Apr 8, 2020 · 11 comments · Fixed by #40184
Open
Tracked by #45022

[Bullet] 3d physics stepping is two frames late for bullet physics #37702

huhund opened this issue Apr 8, 2020 · 11 comments · Fixed by #40184

Comments

@huhund
Copy link

huhund commented Apr 8, 2020

Godot version:

3.2.1-stable

OS/device including version:

Mac

Issue description:

3d physics stepping is two frames late using bullet physics. Expected would be that it is one frame late.

Steps to reproduce:

Apply either velocity or force to a 3d rigid body. You will notice that the object moves two frames after you apply the velocity.

Minimal reproduction project:

Create a 3d scene and add rigid body with this script.

extends RigidBody

var frame = 0

func _ready():
	pass # Replace with function body.

func _physics_process(delta):
	match frame:
		10:
			linear_velocity = Vector3(1,0,0)
		12:
			linear_velocity = Vector3(0,0,0)

	force_update_transform()
	print("frame: " + str(frame) + " vel " + str(linear_velocity) +" " + str(transform.origin))

	frame += 1

The output is

frame: 9 vel (0, 0, 0) (0, 0, 0)
frame: 10 vel (1, 0, 0) (0, 0, 0)
frame: 11 vel (1, 0, 0) (0, 0, 0)
frame: 12 vel (0, 0, 0) (0.1, 0, 0)
frame: 13 vel (0, 0, 0) (0.2, 0, 0)
frame: 14 vel (0, 0, 0) (0.2, 0, 0)

Expected would be that body has moved at frame 11.

** Note **

Using godot physics is the update is only one frame late. Hence bullet physics works differently.

Create equivalent script for 2d. You will notice that the body moves on frame 11. Hence, 2d physics works correctly.

@huhund huhund changed the title 3d physics stepping is two frames late 3d physics stepping is two frames late for bullet physics Apr 8, 2020
@Calinou
Copy link
Member

Calinou commented Apr 9, 2020

cc @AndreaCatania

@AndreaCatania AndreaCatania self-assigned this Apr 9, 2020
@AndreaCatania AndreaCatania added this to the 3.2 milestone Apr 9, 2020
@Calinou
Copy link
Member

Calinou commented Apr 26, 2020

@huhund Does this occur if you use _integrate_forces(state) instead of _physics_process(delta)? This is generally recommended to decrease RigidBody latency by one frame.

@huhund
Copy link
Author

huhund commented May 1, 2020

Thanks Calinou for looking into this.

  • No, _integrate_forces doesn't apply velocity correctly. Same issue persist also if apply impulse instead of setting velocity.

    • The only case that works correctly is in 2d-physics using _physics_process.
    • So a new bug actually surfaced: using 2d and _integrate_forces the physics is one frame late
  • Also, update order is different between Bullet 3D and Godot 2D physics

bullet 3d is

  • _physics_process
  • _integrate_forces
  • _process
  • ( _process ... )

while godot 2d is

  • _physics_process
  • _process
  • ( _process ... )
  • _integrate_forces

I added a test project to github: https://github.com/huhund/godot_tests.git
Where the 4 uses cases are implemented


  • Godot 2D single threaded physics, setting velocity in _physics_process
    • position is applied as expected :)
  • Godot 2D single threaded physics, setting velocity in _integrate_forces
    • position is applied one frame late :(
  • Bullet 3D, setting velocity in _physics process
    • position is applied one frame late :(
  • Bullet 3D, setting velocity in _integrate_forces
    • position is applied one frame late :(

I hope this info is helping. Thanks for a great engine.

@huhund
Copy link
Author

huhund commented May 10, 2020

I tried to figure this out on my own. Thankfully the source code of Godot is very well structured and easy to read - big thanks for that.

Anyway, the situation looks like this to me:

Bullet library does not return the most resent position until the pre-tick in the next frame. This sound a bit weird to me but after a lot of log outputs, this is what it looks like.

  • Currently the update for bullet looks likes
  1. _physics_process
  2. bullet::stepSimulation
    2.1 pre-tick
    foreach object
    apply xform from prev frame
    _integrate_forces
    2.2. tick (most recent xform not available)
  3. _process

One might think that a work around would be be to never use _physics_process and only rely on _integrate_forces. However, this would conflict with e.g. the 2D physics works. Also, the _integrate_forces is called right after the xform is applied. We wouldn't be able to trust that other objects in the scene have yet had their xforms synced.

  • Conclusion

I would suggest that we change so that _physics_process is called from insde the pre-tick. And split the RigidBody::_direct_state_changed functions so that transforms are applied before any process or integrate functions. Like this:

  1. bullet::stepSimulation
    1.1 pre-tick
    foreach object
    apply xform from prev frame
    foreach object
    _physics_process
    foreach object
    _integrate_forces
    1.2. tick (most recent xform not available)
  2. _process

Maybe this setup would make it more stable? What do you guys think?

It's not perfect because the rendering will always use transforms that are one frame late. But in case we can't read the most recent transforms from bullet there is not much we can do. At least it is not two frames late.

@huhund
Copy link
Author

huhund commented Aug 12, 2020

Big thanks for looking into this.

However, can we keep this bug report open? I can still see the two frame issue for Bullet 3D physics in 3.2.3.RC3.

I think the issue is that Bullet library does not return the most resent position until the Bullet pre-tick callback in the next frame.

Currently I can work around the issue just by using Godot 3D physics.

@AndreaCatania
Copy link
Contributor

Probably this is not yet back ported?

@AndreaCatania AndreaCatania reopened this Aug 12, 2020
@huhund
Copy link
Author

huhund commented Aug 12, 2020

The 3.2.3.RC3 release log says it should have the #40184 commit. I'm happy to test again later if I had the wrong version.

@madmiraal
Copy link
Contributor

My understanding is that issues should be closed if they're fixed in master.

#40184 was backported (#40185) but then reverted (with 10544f1), because of regression issues. It will be reapplied with #40788, but it depends on whether #40486 is considered a bug or not.

The 3.2.3.RC3 release log says it should have the #40184 commit.

The release log needs to be updated to reflect the reversion.

@pouleyKetchoupp pouleyKetchoupp changed the title 3d physics stepping is two frames late for bullet physics [Bullet] 3d physics stepping is two frames late for bullet physics Jan 15, 2021
@fabriceci fabriceci modified the milestones: 4.0, 3.x Mar 26, 2022
@m4nu3lf
Copy link
Contributor

m4nu3lf commented May 22, 2022

I was impacted by this issue too. The main problem for me is raycasting from vehicles moving at high velocity. The raycast ends up picking the vehicle itself. I tried to use the body's direct physics state. I would be happy with this solution, but there is still a one-frame lag. I think one of the frames is the flushing happening at the start of the next frame instead of at the end of the current. But the one from the direct body state seems a deeper issue in the Bullet code.

@huhund
Copy link
Author

huhund commented May 30, 2022

I was impacted by this issue too. The main problem for me is raycasting from vehicles moving at high velocity. The raycast ends up picking the vehicle itself. I tried to use the body's direct physics state. I would be happy with this solution, but there is still a one-frame lag. I think one of the frames is the flushing happening at the start of the next frame instead of at the end of the current. But the one from the direct body state seems a deeper issue in the Bullet code.

Can you use Godot physics instead? Or do you need a specific feature from Bullet?

@m4nu3lf
Copy link
Contributor

m4nu3lf commented May 30, 2022

I was impacted by this issue too. The main problem for me is raycasting from vehicles moving at high velocity. The raycast ends up picking the vehicle itself. I tried to use the body's direct physics state. I would be happy with this solution, but there is still a one-frame lag. I think one of the frames is the flushing happening at the start of the next frame instead of at the end of the current. But the one from the direct body state seems a deeper issue in the Bullet code.

Can you use Godot physics instead? Or do you need a specific feature from Bullet?

No, but I have patched my build for the moment. The original poster is experiencing a one-frame lag, not two. I was experiencing two because I was tinkering with the source code and introducing an extra lag frame.
The reason I was doing that was to expose the bullet's substeps parameter. I might create a proposal and if accepted I might just create a PR from my patch.

@Chaosus Chaosus modified the milestones: 3.x, 3.5 May 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment