Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kinematic character controller collision groups not working #497

Open
DevinLeamy opened this issue Jul 2, 2023 · 0 comments
Open

Kinematic character controller collision groups not working #497

DevinLeamy opened this issue Jul 2, 2023 · 0 comments

Comments

@DevinLeamy
Copy link

DevinLeamy commented Jul 2, 2023

Edit

You can fix this by adding the CollisionGroups component to the entity as well as setting the filter_groups feild inside of the KinematicCharacterController.

Overview

The KinematicCharacterController collision groups filters are not working as expected. If we assign CollisionGroups::new(Group::GROUP_1, Group::GROUP_2) to two character controllers we would not expect them to collide as per the docs:

An interaction is allowed between two filters a and b when two conditions are met simultaneously:

The groups membership of a has at least one bit set to 1 in common with the groups filter of b.
The groups membership of b has at least one bit set to 1 in common with the groups filter of a.

In other words, interactions are allowed between two filter iff. the following condition is met:
(self.memberships & rhs.filter) != 0 && (rhs.memberships & self.filter) != 0

However, they do collide.

Investigation

The correct QueryFilter is being sent to the KinematicCharacterController::move_shape method so, from my testing, the problem lies in there.

Example

  • [WASD] to move
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;

#[derive(Clone, Bundle)]
pub struct KinematicColliderBundle {
    pub kinematic: KinematicCharacterController,
    pub collider: Collider,
    pub collider_scale: ColliderScale,
    pub velocity: Velocity,
    pub locked_axes: LockedAxes,
    pub ccd: Ccd,
}

impl Default for KinematicColliderBundle {
    fn default() -> Self {
        Self {
            kinematic: KinematicCharacterController {
                up: Vec3::Y,
                autostep: Some(CharacterAutostep {
                    max_height: CharacterLength::Absolute(0.05),
                    min_width: CharacterLength::Absolute(0.05),
                    include_dynamic_bodies: false,
                }),
                ..default()
            },
            collider: Collider::cuboid(1., 1., 1.),
            collider_scale: ColliderScale::Absolute(Vec3::new(1., 1., 1.)),
            velocity: Velocity::zero(),
            locked_axes: LockedAxes::ROTATION_LOCKED | LockedAxes::TRANSLATION_LOCKED_Z,
            ccd: Ccd::enabled(),
        }
    }
}

fn main() {
    App::new()
        .insert_resource(ClearColor(Color::rgb(
            0xF9 as f32 / 255.0,
            0xF9 as f32 / 255.0,
            0xFF as f32 / 255.0,
        )))
        .add_plugins(DefaultPlugins)
        .add_plugin(RapierPhysicsPlugin::<NoUserData>::default())
        .add_plugin(RapierDebugRenderPlugin::default())
        .add_startup_system(setup_graphics)
        .add_startup_system(setup_physics)
        .add_system(input)
        .run();
}

fn setup_graphics(mut commands: Commands) {
    commands.spawn(Camera3dBundle {
        transform: Transform::from_xyz(0.0, 0.0, -30.0)
            .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
        ..Default::default()
    });
}

#[derive(Component)]
struct Controlled;

fn input(
    mut q_player: Query<&mut KinematicCharacterController, With<Controlled>>,
    keyboard_input: Res<Input<KeyCode>>,
) {
    let mut player = q_player.single_mut();

    let power = 0.1;
    if keyboard_input.any_pressed([KeyCode::Up, KeyCode::W, KeyCode::Space]) {
        player.translation = Some(Vec3::new(0.0, power, 0.0));
    }
    if keyboard_input.any_pressed([KeyCode::Down, KeyCode::S]) {
        player.translation = Some(Vec3::new(0.0, -power, 0.0));
    }
    if keyboard_input.any_pressed([KeyCode::Left, KeyCode::A]) {
        player.translation = Some(Vec3::new(power, 0.0, 0.0));
    }
    if keyboard_input.any_pressed([KeyCode::Right, KeyCode::D]) {
        player.translation = Some(Vec3::new(-power, 0.0, 0.0));
    }
}

pub fn setup_physics(mut commands: Commands) {
    let group = Some(CollisionGroups::new(Group::GROUP_1, Group::GROUP_2));

    let mut player1 = KinematicColliderBundle {
        ..Default::default()
    };
    let mut player2 = KinematicColliderBundle {
        ..Default::default()
    };
    player1.kinematic.filter_groups = group.clone();
    player2.kinematic.filter_groups = group.clone();
    commands.spawn((
        Controlled {},
        player1,
        TransformBundle {
            local: Transform::from_translation(Vec3::new(0.0, 3.0, 0.0)),
            ..default()
        },
         group.unwrap().clone() // This is the fix (adding it a second time, to the entity)
    ));
    commands.spawn((
        player2,
        TransformBundle {
            local: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
            ..default()
        },
        group.unwrap().clone() // (again)
    ));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant