godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.99k stars 21.17k forks source link

PhysicsMaterial `Bounce` behaves random/broken when enabling continous Collision Detection for a RigidBody3D #69667

Open michael-nischt opened 1 year ago

michael-nischt commented 1 year ago

Godot version

v4.0.beta7.official [0bb1e89fb]

System information

Arch Linux, Nvidia 3080

Issue description

Probably since the collision detection divides the motion into multiple sub-steps but and the "bounce" is only based on the last instead of the total motion?

Steps to reproduce

Launch/play the attached project.

Hold SPACE until the ball slides down the Wall and does not bounce.

Observe that the ball's physical material has a bounce value of 0.5.

Change the BOUNCE constant in ball.gd to true:

const BOUNCE : bool = true

This will disable continuous_cd on the RigidBody3D.

Relaunch and hold SPACE to see the ball bounce properly. (But will tunnel at higher speeds.)

Not that the force / distance / .. are chosen so that no bouncing happens with CD enabled. However, bounces can happen for other values. Probably dependent on the CD steps.

Minimal reproduction project

BounceBug3D.zip

DanilaMihailov commented 1 year ago

Happens for me on v4.0.rc1.official [8843d9ad3]. I have simpler setup, just 2 balls with collision shape radius 0.1 and bounce 1, hovering above ground. One ball with CCD enabled, another one is not. When balls drop, ball with CCD enabled loses all momentum and jumps slightly on the ground. While ball without CCD jumps full height as expected.

One thing I found, is that increasing collision shape radius to 0.5 is enough for bounces work as expected. But I am trying to make a tennis ball :(

Calinou commented 1 year ago

One thing I found, is that increasing collision shape radius to 0.5 is enough for bounces work as expected. But I am trying to make a tennis ball :(

You can probably make the floor collider thicker and disable CCD.

DanilaMihailov commented 1 year ago

One thing I found, is that increasing collision shape radius to 0.5 is enough for bounces work as expected. But I am trying to make a tennis ball :(

You can probably make the floor collider thicker and disable CCD.

It was the first thing I did, after learning about "small fast moving objects". Walls 2m thick helped, but ball still went through sometimes. For now I just use CharacterBody3D, apply gravity to it and calculate bounce with simple code from docs.

With my simplified implementation ball does not go through walls even at speeds 100 times faster, than I used with RigidBody without CCD. Which I don't understand why :)

MasterEvilAce commented 1 year ago

Still an issue with 4.0.1. CCD completely breaks physics. Doing an example project to learn Godot and ran into this issue. RigidBody3D ball and StaticBody3D walls/windows. All objects have 0 gravity, 0 friction, 1.0 bounce.

I spawn a ball (sphere collision of 1m) and apply an impulse in a random direction. With CCD on the ball either A) completely stops on contact with a staticbody OR B) loses around ~50% of its momentum on FIRST bounce. Subsequent bounces usually maintain momentum but randomly a bounce will lose even more momentum until the ball stops completely.

With CCD off, the ball works as expected except now it occasionally passes through a window because it's going so fast (which CCD is needed to fix.)

ghost commented 1 year ago

I've been digging into this and it seems the core problem is with this part of solving for CCD

https://github.com/godotengine/godot/blob/6da4ad16624484398331f393b503f8b5e2888c51/servers/physics_3d/godot_body_pair_3d.cpp#L248

which actually has a comment above the method describing exactly this problem:

https://github.com/godotengine/godot/blob/6da4ad16624484398331f393b503f8b5e2888c51/servers/physics_3d/godot_body_pair_3d.cpp#L165

Basically it appears that, for CCD, Godot modifies the linear velocity so that the body arrives on the next step at the collision point, but that means that any collision response now sees an altered velocity. I'm trying some approaches of instead modifying the current position so that the body arrives at the collision point with the same velocity after the next step. Not sure if it's 100% the right fix, but going to see if I can get something working there.