dimforge / dimforge/bevy_rapier

Tracking simulation steps with interpolation for determinism

Open
#465 1 comment 0 reactions 0 assignees View on GitHub
A-Integration C-Bug D-Difficult P-High S-not-started
Dominant language
Rust
Stars
1.6k
Forks
282
PR merge metrics
No merged PRs in 30d

Description

I am currently building an application where I would like to use interpolation as well as keeping track of inputs to achieve determinism in replays.

In the following code snippet there is no sophisticated way to track the amount of iterations the loop has taken. I looked into the rapier physics pipeline and it does not have a fitting feature either.
https://github.com/dimforge/bevy_rapier/blob/c6bcce4695d596a7a9c8e91748d4dbb3d31f6d13/src/plugin/context.rs#L242-L281

This problem does neither occur in fixed time steps since there the simulation is always only stepped once nor is it a problem in variable time steps since determinism is not a thing there.

A solution would be to either have a counter that is exposed and keeps track of the number of iterations in each schedule cycle or some sort of event / callback that is called whenever a step is taken. Since I don't really see any need for individual callbacks and there also is no additional meaningful information to be delivered, the counter solution does seem more reasonable. The counter could then also be implemented for the other time steps as a constant one for consistency.

A possible implementation could be:
```diff
@@ -24,6 +24,8 @@ use rapier::control::CharacterAutostep;
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Resource)]
pub struct RapierContext {
+ /// Keeps track of physics steps taken in the previous simulation step
+ pub step_counter: i32,
/// The island manager, which detects what object is sleeping
/// (not moving much) to reduce computations.
pub islands: IslandManager,
@@ -235,11 +237,14 @@ impl RapierContext {
time_scale,
substeps,
} => {
+ self.step_counter = 0;
self.integration_parameters.dt = dt;

sim_to_render_time.diff += time.delta_seconds();

while sim_to_render_time.diff > 0.0 {
+ self.step_counter += 1;
+
// NOTE: in this comparison we do the same computations we
// will do for the next `while` iteration test, to make sure we
// don't get bit by potential float inaccuracy.
@@ -285,6 +290,7 @@ impl RapierContext {
time_scale,
substeps,
} => {
+ self.step_counter = 1;
self.integration_parameters.dt = (time.delta_seconds() * time_scale).min(max_dt);

let mut substep_integration_parameters = self.integration_parameters;
@@ -309,6 +315,7 @@ impl RapierContext {
}
}
TimestepMode::Fixed { dt, substeps } => {
+ self.step_counter = 1;
self.integration_parameters.dt = dt;

let mut substep_integration_parameters = self.integration_parameters;
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.