Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bullet] KinematicBody (3D) move_and_collide fails to return KinematicCollision with small velocity #62153

Closed
elim2g opened this issue Jun 17, 2022 · 9 comments

Comments

@elim2g
Copy link

elim2g commented Jun 17, 2022

Godot version

3.5.rc4.official [e047c50]

System information

Win10, GLES3, Bullet Physics

Issue description

When using move_and_collide, it will fail to return a KinematicCollision if the collision resulted from a small velocity. This is a regression from the version of Godot I currently use, 3.4.4 stable.

I have a KinematicBody with a Cylinder CollisionShape which I will move into a StaticBody with a Cube CollisionShape.

With the following code:

func _physics_process(delta):
    var col = move_and_collide(Vector3.DOWN * 0.1 * delta);
    if (col):
        print("Collision");

you will never see "Collision" printed to the output. However, if I change that 0.1 to a 5.0, you will see "Collision" printed.

I've created a minimal repro project to demonstrate.

Steps to reproduce

Load the provided repro projct.
Press play
Note the cylinder touches the cube and does not produce any output. If you want, you can even breakpoint line 18 in KinematicBody.gd and see that the execution never pauses.
Now hop into KinematicBody.gd and modify the 0.1 to be 5.0.
Play the project again and note that we now get the expected collision.

Minimal reproduction project

move_and_collide_problem.zip

@Calinou
Copy link
Member

Calinou commented Jun 17, 2022

@elim2g Can you reproduce this in any of the 3.5 betas and RCs to determine when the regression started?

Also, can you reproduce this after switching the 3D physics engine to GodotPhysics in the Project Settings?

@Calinou Calinou added this to the 3.x milestone Jun 17, 2022
@Calinou Calinou changed the title KinematicBody (3D) move_and_collide fails to return KinematicCollision with small velocity [Bullet] KinematicBody (3D) move_and_collide fails to return KinematicCollision with small velocity Jun 17, 2022
@elim2g
Copy link
Author

elim2g commented Jun 17, 2022

This issue is isolated to Bullet, I cannot reproduce it with GodotPhysics. Will get back shortly with when the regression first appeared.

@elim2g
Copy link
Author

elim2g commented Jun 17, 2022

This regression first appears in beta5 (3.5.beta5.official [815f7fe]. beta1 - beta4 behave as expected. beta5 and every RC reliably reproduce the issue.

@elim2g
Copy link
Author

elim2g commented Jun 18, 2022

Hi, the issue is caused by this commit: 65b3200

Specifically the line in physics_body.cpp: KinematicBody::_move() function,

if (collided && col.collision_safe_fraction < 1)

It appears that in Bullet, with small velocities, it's possible for collided to be true while col.collision_safe_fraction to equal 1, therefore failing the evaluation. If I had to take a guess, this is probably due to margins but that's purely speculation. If I build from source and remove the && col.collision_safe_fraction < 1 part of the conditional, the problem is resolved.

Hope this helps, thanks

@akien-mga akien-mga modified the milestones: 3.x, 3.5 Jun 18, 2022
@rburing
Copy link
Member

rburing commented Jun 18, 2022

The mentioned commit 65b3200 causes collisions generated only from recovery not to be reported by move_and_collide, which I think is a good change (it fixes issues). The problem here is that Bullet doesn't detect a collision during the motion. This is caused by the final argument to convexSweepTest here

dynamicsWorld->convexSweepTest(convex_shape_test, shape_world_from, shape_world_to, btResult, dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration);
namely allowedCcdPenetration, being equal to the (relatively large) constant 0.04.

Setting that parameter to 0.001 fixes this issue. Setting it lower breaks things. I'm not sure what's the best general solution.

@Pixelmusement
Copy link

Pixelmusement commented Jun 25, 2022

I would like to add that I'm encountering a similar issue right now in rc4, but instead of being triggered by small movements it's being triggered by using Bullet in combination with a high Physics FPS, such as 120, and the angle of the collision also matters. The lower the Physics FPS or the more direct the collision (as opposed to at a shallow angle) the less likely this problem occurs. (EDIT: I thought it was affecting GodotPhysics too but I retested and I was mistaken, it's only affecting Bullet.)

For instance, I have a player character able to shoot pulses from a weapon. At a physics rate of 20 FPS, move_and_collide() does its job at all times, but at 120 FPS if the angle of the pulse's movement relative to the surface it hits is only a difference of about 20 degrees, the pulse will just slide along the surface instead. At 240 FPS physics the pulse needs more than a 40 degree angle of impact to not start sliding!

@jitspoe
Copy link
Contributor

jitspoe commented Aug 25, 2022

Can confirm this is an absolutely game-breaking regression for me. Effectively, move_and_collide almost never returns a result, even though there is a collision. I've attached a sample project here:
test_3x_kinematic_collision.zip

On frames where there's a collision, the box turns red. What's interesting is that I also tried doing an additional test_move_and_collide() which has a movement LARGER than the margin, and it still fails to collide. If you press space, you can try to jump, but it will only work when on the ground, so you can get a better idea of how often it's not on the ground.

I'm not really sure why this change to add && col.collision_safe_fraction < 1 was introduced. Removing it appears to fix the issue for me as well. The bugs the pull request referenced seemed to be for 2D stuff, which is completely different. The 3D bug shown in the pull request can be fixed by doing multiple steps of move_and_collide in one frame, adjusting the velocity after there's a collision.

I should probably sync more often. 😅

@akien-mga
Copy link
Member

Fixed by #64875.

@rokasv
Copy link

rokasv commented Oct 31, 2022

Problem still exists in 2D of 3.5.1, which includes the #64875 update.

Attached is the project above, with 3D objects converted to 2D and the problem present: move_and_collide_problem.zip

Vector2.DOWN * 4 * delta and lower velocity does not trigger the collision response
Vector2.DOWN * 5 * delta and higher velocity does

As with the OP, the problem does not exist in 3.4.4

Godot Engine v3.5.1.stable.official.6fed1ffa3 - https://godotengine.org
OpenGL ES 3.0 Renderer: NVIDIA GeForce GTX 1050 Ti/PCIe/SSE2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests

8 participants