#Collision in Bevy_rapier

12 messages · Page 1 of 1 (latest)

hoary lichen
#

Is it possible to somehow combine several adjacent collisions into one, or somehow solve the problem of "slippage" between collisions?

odd adder
#

The slippage is weird indeed! How are you moving your character ? And how big are your colliders ?

hoary lichen
#

The dimensions of the colliders are shown in the video.

The character is moved using this method:

fn player_movement(
        mut entity_query:       Query<(&mut Transform, &mut EntityBase, &mut Velocity, Entity), With<User>>,
        mut move_event:         EventWriter<MovementEntity>,
            keyboard_input:     Res<ButtonInput<KeyCode>>
    ) {
        if entity_query.is_empty() {
            return;
        }

        for (mut _transform, player, mut _vel, entity) in &mut entity_query {
            if player.movable {
                let mut direction = Vec3::ZERO;

                let mut speed_var: f32 = player.speed.0;

                if keyboard_input.pressed(KeyCode::ShiftLeft) {
                    speed_var = player.speed.1;
                }

                if keyboard_input.pressed(KeyCode::KeyW) {
                    direction.y += 1.0;
                }
                if keyboard_input.pressed(KeyCode::KeyS) {
                    direction.y -= 1.0;
                }
                if keyboard_input.pressed(KeyCode::KeyA) {
                    direction.x -= 1.0;
                }
                if keyboard_input.pressed(KeyCode::KeyD) {
                    direction.x += 1.0;
                }

                if direction != Vec3::ZERO {
                    move_event.send(MovementEntity(entity, direction.normalize(), speed_var));
                }
            }
        }
    }
#
#[derive(Event)]
pub struct MovementEntity(pub Entity, pub Vec3, pub f32);

fn handle_move(
    mut query: Query<(
        &mut EntityBase, 
        &mut Transform,
        &mut Velocity
    )>,
    mut event: EventReader<MovementEntity>,
    time: Res<Time>
) {
    if event.is_empty() {
        return;
    }

    for event in event.read() {
        if let Ok((mut entity_base, mut transform, mut _vel)) = query.get_mut(event.0) {
            if event.1 != Vec3::ZERO {
                transform.translation = transform.translation + time.delta_seconds() * event.2 * event.1;
                entity_base.position = Position(transform.translation);
            } else {
                transform.translation = entity_base.position.0
            }
        }
    }
}
#

This is noticeable if you move above 120 units, below everything is plus or minus normal

#

But I'm still worried about falling into the joint of a wall collision

#

The code for creating a player and a wall

let (texture, atlas) = DirectionAtlas::set_sprite("human", &handle_dir);
        let entity = commands.spawn((
            EntityBase {
                speed: Speed(50., 75., 25.),
                health: Health(100.),
                position: Position(Vec3::new(64., 64., 0.)),
                direction: DirectionState::South,
                movable: true,
                ..default()
            },
            SpriteSheetBundle {
                texture,
                atlas,
                transform: Transform {
                    translation: Vec3::new(0.0, 0.0, 0.5),
                    ..default()
                },
                ..default()
            },
            EntityType::Humonoid(HumonoidType::Human),
            EntityNeutrality::Neutral,
            Name::new("Player"),
        ))
        .insert(Velocity::zero())
        .insert(RigidBody::Dynamic)
        .insert(Collider::round_cuboid(2., 2., 0.001))
        .insert(LockedAxes::ROTATION_LOCKED)
        .id();
#
let wall = commands
            .spawn((
                SpriteSheetBundle {
                    texture: handle.image.clone().unwrap(),
                    atlas: TextureAtlas {
                        layout: handle.layout.clone().unwrap(),
                        index: TestTextureAtlas::get_index("wall", &handle),
                    },
                    transform: Transform {
                        translation: Vec3::new(tiled_pos.x as f32 * 16. + 8., tiled_pos.y as f32 * 16. + 8., 0.8),
                        ..default()
                    },
                    ..default()
                },
                RigidBody::Fixed
            ))
            .insert(Collider::cuboid(8., 8.))
            .insert(Name::new("Wall"))
            .id();
odd adder
#

I think your issue is that you have a dynamic rigidbody but you’re setting its position directly, effectively teleporting it and rapier struggles to find its new place.
Possible paths to resolution could be to use forces or use a kinematicrigidbody 🤔

More info there: https://rapier.rs/docs/user_guides/bevy_plugin/rigid_bodies/#rigid-body-type

The real-time simulation of rigid-bodies subjected to forces and contacts is the main feature of a physics engine for

hoary lichen
#

I put KinematicPositionBased and started walking through walls)

odd adder
#

Ah yes you’re right, you’d need to reimplement the KinematicCharacterController.. have you looked at it for inspiration ? Personally I would probably use the rigidbody linvel

hoary lichen
#

Maybe it's because of Velocity, for example, bevy_rapier showed a way to move through the linvel installation. But at that time, I did not like this option, it seems, because of the abnormal movement, or because of the difficulty of unifying the movement of the entity. But even here I doubt it in places.

To begin with, I will try to re-realize the movement, but for me it is secondary. I would rather somehow understand how to combine collisions into one, not calculate them separately.