Notably, the PlayerBundle uses the #[bundle()] on the camera bundle, so the camera bundle's transform is getting reused directly as the player's transform instead of using a separate position for each.
Here's my player, lerp_positions, and physics_update implementation for reference:
struct PlayerBundle {
player: Player,
position: TargetTransform,
velocity: Velocity,
#[bundle()]
camera: Camera3dBundle,
}
fn lerp_positions(mut tick: ResMut<PhysicsTick>, time: Res<Time>, fixed_time: Res<FixedTime>, mut query: Query<(&mut Transform, &TargetTransform)>)
{
tick.stopwatch.tick(time.delta());
let s = tick.stopwatch.elapsed().as_secs_f32() / fixed_time.period.as_secs_f32();
for (mut transform, target) in query.iter_mut() {
transform.translation = transform.translation.lerp(target.0.translation, s);
}
println!("{}",s);
}
fn physics_update(mut tick: ResMut<PhysicsTick>, time: Res<FixedTime>, mut query: Query<(Option<&mut Player>, &mut TargetTransform, &mut Velocity)>) {
tick.stopwatch.reset();
println!("reset");
for (player_option, mut target, mut velocity) in query.iter_mut() {
// Do half the update using last tick's velocity
target.0.translation += velocity.0 * time.period.as_secs_f32() * 0.5;
// Update velocity
// First, apply friction
velocity.0 *= 0.1_f32.powf(time.period.as_secs_f32());
match player_option {
Some(_) => {
let player = player_option.unwrap();
// update velocity with new input
velocity.0 += player.input_dir * player.acceleration;
},
_ => {}
}
// clamp max velocity
velocity.0 = velocity.0.clamp_length_max(8.0);
// Do half the update using the new velocity
target.0.translation += velocity.0 * time.period.as_secs_f32() * 0.5;
}
}