Resolve #867 - Make deltatime use the lowest delta of several frames to avoid 'teleport' effect after single-frame lag spike

This commit is contained in:
HiggsTardigradeTau 2020-12-08 21:07:14 +00:00 committed by Marcel
parent 20b45a1202
commit 57d3a595ce
2 changed files with 26 additions and 3 deletions

View File

@ -54,6 +54,7 @@ pub struct ClockStats {
}
const NUMBER_OF_OLD_DELTAS_KEPT: usize = 100;
const NUMBER_OF_DELTAS_COMPARED: usize = 5;
impl Clock {
pub fn new(target_dt: Duration) -> Self {
@ -75,6 +76,24 @@ impl Clock {
pub fn dt(&self) -> Duration { self.last_dt }
pub fn get_stable_dt(&self) -> Duration {
if self.last_dts.len() < NUMBER_OF_DELTAS_COMPARED {
self.last_dt
} else {
let stable_dt = Duration::from_secs_f32(
self.last_dts
.iter()
.skip(self.last_dts.len() - NUMBER_OF_DELTAS_COMPARED)
.min()
.map_or(self.last_dt.as_secs_f32(), |t| t.into_inner()),
);
if self.last_dt > 2 * stable_dt {
tracing::debug!(?self.last_dt, ?self.total_tick_time, "lag spike detected, unusually slow tick");
}
stable_dt
}
}
/// Do not modify without asking @xMAC94x first!
pub fn tick(&mut self) {
span!(_guard, "tick", "Clock::tick");

View File

@ -634,7 +634,7 @@ impl PlayState for SessionState {
let right = self.scene.camera().right();
let dir = right * axis_right + forward * axis_up;
let dt = global_state.clock.dt().as_secs_f32();
let dt = global_state.clock.get_stable_dt().as_secs_f32();
if self.freefly_vel.magnitude_squared() > 0.01 {
let new_vel = self.freefly_vel
- self.freefly_vel.normalized() * (FREEFLY_DAMPING * dt);
@ -671,7 +671,11 @@ impl PlayState for SessionState {
// Runs if either in a multiplayer server or the singleplayer server is unpaused
if !global_state.paused() {
// Perform an in-game tick.
match self.tick(global_state.clock.dt(), global_state, &mut outcomes) {
match self.tick(
global_state.clock.get_stable_dt(),
global_state,
&mut outcomes,
) {
Ok(TickAction::Continue) => {}, // Do nothing
Ok(TickAction::Disconnect) => return PlayStateResult::Pop, // Go to main menu
Err(err) => {
@ -740,7 +744,7 @@ impl PlayState for SessionState {
global_state,
&debug_info,
&self.scene.camera(),
global_state.clock.dt(),
global_state.clock.get_stable_dt(),
HudInfo {
is_aiming,
is_first_person: matches!(