lightyear_frame_interpolation 0.29.0

IO primitives for the lightyear networking library
Documentation

This module is not related to the interpolating between server updates. Instead, it is responsible for interpolating between FixedUpdate ticks during the Update state.

Usually, the simulation is run during the FixedUpdate schedule so that it doesn't depend on frame rate. This can cause some visual inconsistencies (jitter) because the frames (Update schedule) don't correspond exactly to the FixedUpdate schedule: there can be frames with several fixed-update ticks, and some frames with no fixed-update ticks.

To solve this, we visually display the state of the game with 1 tick of delay. For example if on the Update state we have an overstep of 0.7 and the current tick is 10, we display the state of the game interpolated at 0.7 between tick 9 and tick 10.

Another way to solve this would be to run an extra 'partial' simulation step with 0.7 dt and use this for the visual state.

To enable FrameInterpolation:

  • register an interpolation rule for the component or bundle. Existing interpolation rules are reused by default; if the component should not use delayed interpolation history, register it with InterpolationFns::no_history.
  • FrameInterpolation is not enabled by default; add [FrameInterpolationPlugin] manually
  • To enable FrameInterpolation on a given entity, add the type-erased [FrameInterpolate] marker to it manually

Frame interpolation writes through Bevy's change-detection-aware component access. Systems ordered after [FrameInterpolationSystems::Interpolate] can therefore use Changed<C> to react to the visual value.

# use lightyear_frame_interpolation::prelude::*;
# use lightyear_interpolation::prelude::*;
# use bevy_app::App;
# use bevy_ecs::prelude::*;

# #[derive(Component, PartialEq, Clone, Debug)]
# struct Component1(f32);
# fn lerp_component(start: Component1, end: Component1, t: f32) -> Component1 {
#     Component1(start.0 + (end.0 - start.0) * t)
# }

let mut app = App::new();
app.add_plugins(FrameInterpolationPlugin);
app.interpolate_with::<Component1>(InterpolationFns::no_history(lerp_component));

fn spawn_entity(mut commands: Commands) {
    commands.spawn(FrameInterpolate);
}