Closed DanteMarshal closed 7 months ago
Made a few changes, after removing the for
loop on mouse.read()
I don't get the panics anymore.
I don't know if I'm doing something wrong or if this is really a bug !
Here's the new code, I still get the panics when I uncomment the mouse.read()
loop.
use bevy::{
input::{keyboard::KeyboardInput, mouse::MouseMotion, ButtonState},
prelude::*,
};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(bevy_framepace::FramepacePlugin)
.add_systems(Startup, setup)
.add_systems(Update, update)
.run();
}
fn update(
mut cube: Query<(&mut Player, &mut Transform)>,
mut keys: EventReader<KeyboardInput>,
mut mouse: EventReader<MouseMotion>,
time: Res<Time>,
) {
let mut player = cube.single_mut();
for event in keys.read() {
if event.key_code == KeyCode::KeyR {
match event.state {
ButtonState::Pressed => player.0.move_direction.y = 1.0,
ButtonState::Released => player.0.move_direction.y = 0.0,
}
}
if event.key_code == KeyCode::KeyF {
match event.state {
ButtonState::Pressed => player.0.move_direction.y = -1.0,
ButtonState::Released => player.0.move_direction.y = 0.0,
}
}
if event.key_code == KeyCode::KeyW {
match event.state {
ButtonState::Pressed => player.0.move_direction.z = -1.0,
ButtonState::Released => player.0.move_direction.z = 0.0,
}
}
if event.key_code == KeyCode::KeyS {
match event.state {
ButtonState::Pressed => player.0.move_direction.z = 1.0,
ButtonState::Released => player.0.move_direction.z = 0.0,
}
}
if event.key_code == KeyCode::KeyD {
match event.state {
ButtonState::Pressed => player.0.move_direction.x = 1.0,
ButtonState::Released => player.0.move_direction.x = 0.0,
}
}
if event.key_code == KeyCode::KeyA {
match event.state {
ButtonState::Pressed => player.0.move_direction.x = -1.0,
ButtonState::Released => player.0.move_direction.x = 0.0,
}
}
}
let translation = time.delta_seconds()
* Vec3::new(
player.1.local_x().dot(player.0.move_direction),
player.1.local_y().dot(player.0.move_direction),
player.1.local_z().dot(player.0.move_direction),
);
player.1.translation += translation;
// for event in mouse.read() {
// player
// .1
// .rotate_local_axis(time.delta_seconds() * Vec3::X, event.delta.y);
// player
// .1
// .rotate_local_axis(time.delta_seconds() * Vec3::Y, event.delta.x);
// }
player.1.set_changed();
}
fn setup(
mut framepace: ResMut<bevy_framepace::FramepaceSettings>,
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
framepace.limiter = bevy_framepace::Limiter::from_framerate(30.0);
// circular base
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(4.0)),
material: materials.add(Color::WHITE),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(Color::rgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
// light
commands.spawn(PointLightBundle {
point_light: PointLight {
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
// camera
commands.spawn((
Player::default(),
Camera3dBundle {
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
));
}
#[derive(Default, Component)]
struct Player {
move_direction: Vec3,
}
I haven't looked really deeply into this yet, but I'm guessing this is caused by repeated calls to rotate_local_axis
causing the rotation quaternion to denormalize, since Transform::rotate_local
just multiplies the current rotation quaternion by another one (so errors accumulate).
Oh, on second glance, Quat::from_axis_angle
, which is called in Transform::rotate_local_axis
, expects the input vector to be normalized. It looks like our API doesn't explain this, but the first input to rotate_local_axis
is definitely supposed to be a unit vector.
Well, this is a user error that is now solved by #12986, So I'm closing this as completed, feel free to open this again if you see something wrong!
Thanks guys. One question though, I still didn't get what the cause is.
I'm guessing it's because I wrote time.delta_seconds() * Vec3::X
which is not a unit vector, so in that case will it be fixed by rotate_local_axis(Vec3::X, time.delta_seconds() * event.delta.y)
?
Just wanna make sure I understood correctly.
The problem is that the Vec is not normalized. If you have a look at the internal function, it uses a function Quat::from_axis (IIRC) that will panic if you use a denormalized vec. So, to solve this, you just need to normalize your final vec. Now, using Dir3, we will assert that everything is normalized.
The problem is that the Vec is not normalized. If you have a look at the internal function, it uses a function Quat::from_axis (IIRC) that will panic if you use a denormalized vec. So, to solve this, you just need to normalize your final vec. Now, using Dir3, we will assert that everything is normalized.
I don't think it actually panics unless glam_assert
is enabled, but it would still cause other weird behaviors which could easily be at the root of the problem (e.g. causing the quaternion to denormalize).
That being said, do try using a normalized vector as input and seeing if the crash still occurs; if it does, you might need to renormalize the rotation quaternion every so often.
I'm getting a panic on this on 0.14 when I leave my game running long enough that it randomly happens.
thread 'Compute Task Pool (6)' panicked at /home/mramirez/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_transform-0.14.0/src/components/transform.rs:264:44:
In my code I'm just doing calls to transform.forward() but it seems there's a scenario that causes the Dir3::new(self.rotation * Vec3::Z).unwrap()
in local_z
to panic. I'll see if I can gather more context for why this happens.
Are you changing the transform incrementally? The only way that unwrap should ever fail is if the quaternion representing the rotation is extremely denormalized.
Are you changing the transform incrementally?
Not.. intentionally... I'm using Avian physics and the transform of this object is being modified by impulses.. it looks like at some point the rotation gets set to this denormalized value. So this panics
Transform::from_rotation(Quat::from_array([0.0, -0.0, 0.0, 0.0])).forward();
I'm unsure what causes the rotation to end up 0.0, -0.0, 0.0, 0.0
, but it's pretty unexpected that calling Transform::forward can panic.
Bevy version
The release number or commit hash of the version you're using.
[Optional] Relevant system information
What you did
I'm trying to learn bevy, and I was making a very simple scene to move a cube. Here's the code :
What went wrong
Panics on one of the
local_?
calls, Here's the backtrace from one of them :Additional information
I think it happens the moment I press a key that is the opposite of a key I pressed before. For example, if I press Left (KeyA) nothing happens, but then pressing Right (KeyS) will panic afterwards.