#Rapier KinematicCharacterControllerOutput not present

14 messages · Page 1 of 1 (latest)

grave pumice
#

I'm trying to query the kinematic character controller output on my player like so

// src/fps_game/controller.rs
pub fn update_physics(
    time: Res<Time>,
    mut q_player_transform: Query<
        (
            &Transform,
            &InputVector,
            &Speed,
            &mut Velocity,
            &mut KinematicCharacterController,
            &KinematicCharacterControllerOutput,
        ),
        With<Player>,
    >,
    settings: Res<settings::Settings>,
) {
  // ...
}
#

However trying to run this system panics

thread '<unnamed>' panicked at src/fps_game/controller.rs:149:28:
called `Result::unwrap()` on an `Err` value: NoEntities("bevy_ecs::query::state::QueryState<(&bevy_transform::components::transform::
Transform, &fps_test::fps_game::controller::InputVector, &fps_test::fps_game::controller::Speed, &mut fps_test::fps_game::controller:
:Velocity, &mut bevy_rapier3d::control::character_controller::KinematicCharacterController, &bevy_rapier3d::control::character_contro
ller::KinematicCharacterControllerOutput), bevy_ecs::query::filter::With<fps_test::fps_game::controller::Player>>")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `fps_test::fps_game::controller::update_physics`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

Removing the KinematicCharacterControllerOutput from the query gets rid of the panic

This is the code for spawning the player

pub fn spawn_player(mut commands: Commands) {
    let player = PlayerBundle {
        marker: Player,
        speed: Speed(10.0),
        rigidbody: RigidBody::KinematicPositionBased,
        collider: Collider::capsule(
            Vec3::new(0.0, -PLAYER_HEIGHT * 0.25, 0.0),
            Vec3::new(0.0, PLAYER_HEIGHT * 0.25, 0.0),
            PLAYER_HEIGHT * 0.25,
        ),
        controller: KinematicCharacterController::default(),
        transform: SpatialBundle {
            transform: Transform::from_xyz(0.0, PLAYER_HEIGHT / 2.0, 0.0),
            ..Default::default()
        },
        ..Default::default()
    };

    commands.spawn(player).with_children(|parent| {
        parent.spawn(PlayerWorldCameraBundle {
            marker: PlayerWorldCamera,
            camera: Camera3dBundle {
                transform: Transform::from_xyz(0., CAMERA_HEIGHT, 20.0),
                ..Default::default()
            },
        });
    });
}
#

What's confusing is that the rapier docs say that the output will be automatically inserted on the same entity as the one with the character controller

#

Is there any example projects with kinematic controller 3d that i can take a look at? there is snippets of code in the rapier docs but no full examples

#

i basically just want to be able to check if the player is grounded

left portal
#

So, I don't really know the reasoning behind it, but the example in the bevy rapier3d repo uses an Option to wrap the Output: https://github.com/dimforge/bevy_rapier/blob/master/bevy_rapier3d/examples/character_controller3.rs

fn player_movement(
    time: Res<Time>,
    mut input: ResMut<MovementInput>,
    mut player: Query<(
        &mut Transform,
        &mut KinematicCharacterController,
        Option<&KinematicCharacterControllerOutput>,
    )>,
    mut vertical_movement: Local<f32>,
    mut grounded_timer: Local<f32>,
)
GitHub

Official Rapier plugin for the Bevy game engine. Contribute to dimforge/bevy_rapier development by creating an account on GitHub.

#

also in that example they use this to check if the player is grounded:

    if output.map(|o| o.grounded).unwrap_or(false) {
        *grounded_timer = GROUND_TIMER;
        *vertical_movement = 0.0;
    }
left portal
#

Although it is kind of strange, cuz in their user guide, they don't use an Option? https://rapier.rs/docs/user_guides/bevy_plugin/character_controller/

/* Read the character controller collisions stored in the character controller’s output. */
fn read_character_controller_collisions(
    mut character_controller_outputs: Query<&mut KinematicCharacterControllerOutput>,
) {
    for mut output in character_controller_outputs.iter_mut() {
        for collision in &output.collisions {
            // Do something with that collision information.
        }
    }
}
grave pumice
#

i did a little fiddling around

#

turns out that the controlleroutput is inserted after the first update with the controller

#

or so i think

#

so i just inserted the default controller output

#

and it works like a charm so far