Skip to content

Conversation

@UndefinedBHVR
Copy link

Objective

  • Implements a collide and slide character controller based on the implementation I wrote for my personal project, Vidar.

Solution

  • Adds a new example, Collide and Slide 3d. Implements the a kinematic character controller using the algorithm from Kasper Fauerby + my own personal research in changes.
  • The character controller is a multipass resolver, gravity is handled separately to ensure actual movement logic doesn't fight with it. For some games, this is preferable, for others not so much. We may want to document that.

Changelog

This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.

  • Implemented Collide and Slide 3d character controller example.

Migration Guide

This section is optional. If there are no breaking changes, you can delete this section.

  • No actions required.

@UndefinedBHVR UndefinedBHVR marked this pull request as draft December 25, 2024 23:57
@fr33zing
Copy link

Hi, I'm working on a KCC and I've used some parts of yours. I noticed an issue where any slope is climbable. I checked your Vidar code and it seems like this issue would be present there too.

I have a solution to this, here's a snippet from mine:

let too_steep = hit.normal1.angle_between(Vec3::Y) > MAX_SLOPE_DEGREES.to_radians();
let normal = if pass == Pass::Movement && too_steep {
    (hit.normal1 * Vec3::new(1.0, 0.0, 1.0)).normalize()
} else {
    hit.normal1
};

Then normal goes into calculate_sliding_velocity. This makes steep slopes act like walls. I'm curious if you'd consider this a proper solution or not.

@janhohenheim janhohenheim mentioned this pull request Nov 20, 2025
7 tasks
@janhohenheim janhohenheim added the S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged label Nov 24, 2025
@janhohenheim
Copy link
Member

Closing in favor of #894, which takes a lot of inspiration from this PR :)

Jondolf pushed a commit that referenced this pull request Nov 25, 2025
# Objective

- Resolves #438
- Supersedes #606
- Almost all kinematic character controllers use an algorithm called "move and slide", aka "collide and slide", "step slide", and similar, at their core
- This algorithm basically says 
  - Please move in this direction
  - if you collide with anything, slide along it
  - make sure you're not intersecting with anything, and report everything you collide with
  - see https://www.youtube.com/watch?v=YR6Q7dUz2uk for a video explanation

## Solution

- Provide a `MoveAndSlide` `SystemParam` with an eponymous `move_and_slide` function
  - Implemented as a pure function, i.e. it does not mutate the ECS by itself
  - Returns a new position and velocity after movement and sliding along surfaces is complete
  - Every collision encountered during the slide is fed to a callback for optional processing. The callback is allowed to early-abort the slide.
  - Note: Currently, `move_and_slide` should be used to modify `Transform`, not `LinearVelocity`. The returned velocity should be stored elsewhere and passed to the next move and slide call to preserve momentum. ECS integration with `LinearVelocity` will be added later.
- High level overview: (edited by @Jondolf to match new multi-plane solver)
  1. Initial Gauss-Seidel depenetration pass
  2. For each iteration, until movement is done or max iterations reached:
     - Sweep the shape along the velocity vector
     - If we hit something, move up to the hit point
     - Collect contact planes
     - Depenetrate based on intersections
     - Project velocity to be parallel to all contact planes
- Inspirations
  - [kcc_prototypes](https://github.com/Ploruto/kcc_prototyping): general API shape, various code snippets
  - Box2D's [Character Mover](https://box2d.org/documentation/md_character.html): vector clipping and misc. ideas
  - Quake 3's [PM_SlideMove](https://github.com/id-Software/Quake-III-Arena/blob/dbe4ddb10315479fc00086f08e25d968b4b43c49/code/game/bg_slidemove.c#L45): 3D plane solver
  - [Solar Ash](https://store.steampowered.com/app/1867530/Solar_Ash/)'s implementation, as per [Tech Breakdown: Collision Sliding](https://blog.littlepolygon.com/posts/sliding/): depenetration
  - [Tweets](https://x.com/PhilippeStA/status/1233008602551590913) by Philippe St-Amand: new multi-plane solver that projects onto a convex cone, inspired by some of Philippe's ideas
- Prior work in Avian KCC tech and comparison
  - [kcc_prototypes](https://github.com/Ploruto/kcc_prototyping):
    - very similar API
    - switched to Q3 plane solver, but then a hard-drive failure erased the progress.
    - no depenetration
  - [avian_collide_and_slide](https://github.com/tracefree/avian_collide_and_slide): 
    - uses Q1 plane solving
    - no depenetration
  - [bevy_fps_controller](https://github.com/qhdwight/bevy_fps_controller): 
    - Q1/Source inspired
    - no exposed collide-and-slide
    - no plane solving
    - no depenetration
- Special thanks to @UndefinedBHVR, who spearheaded a first iteration of collide-and-slide that I was able to iterate on and who's breadcrumbs I followed a lot ❤️ 
- TODO:
  - [x] Fix some jitter on plane intersections
  - [x] Write docs
  - [x] Add examples to docs
  - [x] Replace the asset links juuuust before merging
    - See avianphysics/avian_asset_files#1


## Out of Scope for this PR

- Example KCC implementation
  - This is a deep rabbit hole and I'll leave that as a followup to not bloat this PR. 
  - See #450 for a list of minimal character controllers that should be showcased eventually
  - For now, an integration into https://github.com/janhohenheim/character_controller_experiments will serve as proof that a KCC is doable with this API.
- Changing the existing KCC examples
  - I think these should just be entirely rewritten later on
- predicting intersections with moving bodies
- calculating forces to be exerted onto touching dynamic bodies and vice versa
- minimal examples, for now we just have the in-depth testbeds
- a more diverse 2D testbed: requires parsing SVGs like Box2D

## Testing

- [x] 3D testbed
  - `bevy run --example collide_and_slide -p avian3d`
- [x] 2D testbed
  - `bevy run --example collide_and_slide -p avian2d`
- [x] integration in https://github.com/janhohenheim/character_controller_experiments

---

## Showcase

https://github.com/user-attachments/assets/426b0e4e-73ad-490c-acc2-1489eb848066
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants