bevy_xpbd icon indicating copy to clipboard operation
bevy_xpbd copied to clipboard

Add collide and slide kinematic controller

Open UndefinedBHVR opened this issue 1 year ago • 3 comments
trafficstars

Objective

  • https://github.com/Jondolf/avian/issues/438

Solution

  • Introduce a basic collide and slide implementation for a new Kinematic Character Controller example entitled kinematic_character_cas_3d.

Changelog

Note: You can run the new example with cargo run --example kinematic_character_cas_3d

Added

  • Introduced a work in progress collide and slide function based on community work in the Avian Physics channel of the Bevy discord

UndefinedBHVR avatar Aug 11 '24 18:08 UndefinedBHVR

Current noteworthy issues:

  • [x] [FIXED] Character spawns in ground
  • [x] [FIXED] Character gets put in floor at bottom of steep surfaces, and is unable to jump out
  • [ ] Doesn't prevent climbing steep slopes, though gravity does somewhat prevent this.
  • [x] [FIXED] Occasionally invalid values make it to let (velocity_normalized, length) = Dir3::new_and_length(velocity).unwrap();, might be fixed with a close to zero check instead of a zero check
  • [x] [FIXED] Character sometimes bounces when going down slopes.
  • [x] [FIXED] Character slides down non-steep slopes. Needs angle checking with grounding to prevent sliding down.

UndefinedBHVR avatar Aug 11 '24 18:08 UndefinedBHVR

Character slides down non-steep slopes.

This is because right now, apply_gravity applies downward velocity even when standing on the ground. This is problematic both because of this issue and because when the character walks off a cliff it immediately starts falling down at a very high velocity instead of a gradually increasing gravitational force.

When a Grounded check is added to apply_gravity like this:

fn apply_gravity(
    time: Res<Time>,
    mut controllers: Query<(&ControllerGravity, &mut CharacterController, Option<&Grounded>)>,
) {
    for (gravity, mut character_controller, grounded) in &mut controllers {
        if grounded.is_some() && character_controller.velocity.y < 0.0 {
            character_controller.velocity.y = 0.0;
        } else {
            character_controller.velocity += gravity.0 * time.delta_seconds();
        }
    }
}

And the ShapeCaster ground checking component's with_max_time_of_impact(0.2) is changed to 0.05 in order to have a more reasonable gap between the character capsule and the ground, this no longer happens.

Since Grounded is only added when standing on a slope that doesn't exceed max_slope_angle, this retains the sliding down on slopes that are too steep.

The downside of this is that now when walking down a slope, the character doesn't stick to it. But that can be solved by adding ground snapping logic to the collide and slide algorithm.

jirisvd avatar Aug 11 '24 20:08 jirisvd

Accidentally pushed commit from an experiment branch, force pushed to undo it.

UndefinedBHVR avatar Aug 13 '24 17:08 UndefinedBHVR