dimforge / bevy_rapier

Official Rapier plugin for the Bevy game engine.
https://rapier.rs
Apache License 2.0
1.26k stars 259 forks source link

Running in bevy's FixedTimestep #355

Closed paholg closed 1 year ago

paholg commented 1 year ago

Hello! I would like to use bevy_rapier, and run it at a fixed time-step, independent of my game's frame-rate.

I was able to accomplish this with bevy 0.9 and bevy_rapier 0.19 by using iyes_loopless, setting up some custom stages analogous to bevy_rapier's stages, calling RapierPhysicsPlugin::.with_default_system_setup(false), and setting up the systems myself in my custom, fixed-timestep stages.

If interested, you can see the code here: https://github.com/paholg/gam/blob/fb2af451e8bc3e993365f351515ab08f2e6d6d3e/src/physics.rs#L35-L61


I have now updated to bevy 0.10, bevy_rapier 0.21, and removed iyes_loopless, but cannot get the same fixed-timestep behavior out of bevy_rapier. I am similarly calling RapierPhysicsPlugin::with_default_system_setup(false), and reproducing the logic that would be run by the default system setup, only placing the sets before(CoreSet::FixedUpdate) instead of at their default place. But the physics is not running at a fixed timestep; by toggling vsync, for example, there is a significant difference in how fast things move.

If interested, this code is here: https://github.com/paholg/gam/blob/56e9531d9199839634df03e11b97989a4ba4eb7a/src/physics.rs#L31-L60


I would be happy with any advice on how to get bevy_rapier running at a fixed timestep. Thank you!

atomicbeef commented 1 year ago

Hey @paholg ! I'm setting up Rapier to run in a fixed time step schedule now, and I noticed a few things in your linked snippet that may be causing your problem.

  1. You use app.configure_sets(). According to the documentation, this adds the sets to the default schedule, while you want them added to CoreSchedule::FixedUpdate (or whatever other fixed schedule you may be using). I replaced that section with the following (I still have to add ordering with other sets in the fixed schedule):
    app.edit_schedule(CoreSchedule::FixedUpdate, |schedule| {
    schedule.configure_sets((
        PhysicsSet::SyncBackend,
        PhysicsSet::SyncBackendFlush,
        PhysicsSet::StepSimulation,
        PhysicsSet::Writeback,
    ).chain());
    })
  2. When you do the app.add_systems() call, you don't specify a schedule, so the systems get added to the default schedule. I just added .in_schedule(CoreSchedule::FixedUpdate) after the .in_base_set() call in my code.

Hopefully this was helpful in solving your problem 😄

allsey87 commented 1 year ago

@Aceeri, @sebcrozet: is the solution by @atomicbeef still valid now that #385 has been merged?

Aceeri commented 1 year ago

@Aceeri, @sebcrozet: is the solution by @atomicbeef still valid now that #385 has been merged?

I would just worry about the systems reliant on events/removal detection not being in a non-FixedUpdate, otherwise the physics backend may not get updated accordingly. Particularly here: https://github.com/dimforge/bevy_rapier/pull/385/files#diff-b677a0606d6f33a6b13ee1a417857f817fc31b0fdadacc1ddb8f9426db110211R224

Aside from that it should still work as before. That PR is just a convenience method for a common usecase.