dimforge / rapier

2D and 3D physics engines focused on performance.
https://rapier.rs
Apache License 2.0
3.89k stars 242 forks source link

Kinematic Character Controller move_shape clips through objects when desired_translation is zero #485

Open stefnotch opened 1 year ago

stefnotch commented 1 year ago

Issue We have a moving kinematic rigidbody. And this rigidbody can push our KinematicCharacterController around. As in, the character controller gets lushed away when something moves into it.

However, when we call move_shape with different desired_translation, then it behaves unexpectedly.

Steps to reproduce Remove https://github.com/dimforge/rapier/blob/89e3d7650c84f96893376a79cbc120aeaeb74785/src_testbed/testbed.rs#L765 , which effectively disables gravity. So, when not pressing any keys, then the entire vector that is passed to move_shape will be [0.0, 0.0, 0.0]. And then, the bug can be reproduced.

  1. Remove that line of code
  2. Start testbed cargo run --bin all_examples3
  3. Switch to character controller
  4. Move in the way of the moving platform
  5. When not pressing any key, then the moving platform will move into the character controller.

all_examples3_2023-04-24-0292.webm

Our setup in our game where we noticed it

We have a rigidbody with a box collider, which is KinematicPositionBased. We're moving that rigidbody back and forth. (rigid_body.set_next_kinematic_translation(...);)

We have a floor, which is one big box collider.

We have a KinematicCharacterController, which mostly just follows the examples from the documentation. We're supplying it with a desired_translation every frame. And then we use the returned effective movement to move the character controller.

Additional notes

Apparently the while loop in rapier's character controller gets skipped when passed a zero vector. https://github.com/dimforge/rapier/blob/89e3d7650c84f96893376a79cbc120aeaeb74785/src/control/character_controller.rs#L215

(The stairs logic also has some "skip if zero" logic, but I think that's unrelated)

YouSafe commented 1 year ago

Here is another demo example highlighting the issue (the example must be registered first in the all_examples3.rs file):

https://gist.github.com/YouSafe/6f49c4c35e65a0edfa0d06f1a7915514

It is just a moving cube which has a position-based kinematic rigid body moving back and forth and the usual kinematic character controller from the testbed.

The behaviour when gravity is applied to the character controller:

https://github.com/dimforge/rapier/blob/89e3d7650c84f96893376a79cbc120aeaeb74785/src_testbed/testbed.rs#L765

https://user-images.githubusercontent.com/12512150/234235846-b89fce60-b82f-4d5c-b746-bffbad83d337.mp4

The behaviour when no gravity is applied to the character controller:

https://user-images.githubusercontent.com/12512150/234235349-023944a4-2374-41a7-b94b-bb0f209892f5.mp4

I hope this demo better visualizes the issue!

sebcrozet commented 1 year ago

Thanks for providing these examples. The character-controller not being pushed when its desired movement is zero is by-design (because of the early-exit identified by @stefnotch) to save computation times. But, clearly, it’s not the behavior anybody expects in practice, so we can consider this as a bug.