#Making Player Movement Framerate Independent

2 messages · Page 1 of 1 (latest)

late echo
#

in physics.rs:

.add_systems(
                (
                    zero_velocity_on_collision.in_set(PhysicsSystem::ZeroVelocityOnCollision),
                    apply_velocity.in_set(PhysicsSystem::ApplyVelocity),
                )
                    .distributive_run_if(in_state(GameState::Playing))
                    .in_schedule(CoreSchedule::FixedUpdate),
);

fn apply_velocity(
    mut physics_qry: Query<(&mut KinematicCharacterController, &mut Velocity, &Friction)>,
) {
    for (mut char_ctrl, mut vel, friction) in physics_qry.iter_mut() {
        vel.linvel.y -= DEFAULT_GRAVITY;

        if vel.linvel.x.is_sign_positive() {
            vel.linvel.x = f32::max(vel.linvel.x - friction.coefficient, 0.);
        } else if vel.linvel.x.is_sign_negative() {
            vel.linvel.x = f32::min(vel.linvel.x + friction.coefficient, 0.);
        }
        vel.linvel.x = vel
            .linvel
            .x
            .clamp(-DEFAULT_TERMINAL_VELOCITY.x, DEFAULT_TERMINAL_VELOCITY.x);

        vel.linvel.y = f32::max(vel.linvel.y, -DEFAULT_TERMINAL_VELOCITY.y);
        char_ctrl.translation = Some(vel.linvel);
    }
}

// zero_velocity_on_collision() isn't really necessary to have here to understand my issue
#

I've tried the following three solutions:

  1. Run both move_player() and apply_velocity() in fixed update
  2. Run both move_player() and apply_velocity() in update (with dt being multplied like this: char_ctrl.translation = Some(vel.linvel * dt);
  3. Run move_player() in update and apply_velocity() in fixed update (which is what I have right now with dt being multiplied in move_player())