Godot version:
3.1 Beta 1
OS/device including version:
Windows 10
Issue description:
When a KinematicBody (3D) collides with a too steep slope (one that is not climbable) the returned vector has a Y value too high for the collision, if this vector is applied to the kinematicbody the result is a flying object.
Steps to reproduce:
Run the attached project, when colliding to the lowest slope the object goes up.
Minimal reproduction project:
KinematicTest.zip
@AndreaCatania : in the attached project there are other two issues: RayShape doesn't push object away from collision and move_and_slide_with_snap with stop_on_slope=true doesn't prevent object from sliding. Before opening another issue I'd like to know if those are errors or I'm doing something wrong.
move_and_slide_with_snap with stop_on_slope=true doesn't prevent object from sliding
This has been fixed yesterday by disabling -ffast-math. The fix will be available in the next beta/RC release.
move_and_slide_with_snap with stop_on_slope=true doesn't prevent object from sliding
This has been fixed yesterday by disabling
-ffast-math. The fix will be available in the next beta/RC release.
@timoschwarzer : did you tested it? I just compiled version 1ff170e67f0044b0a9f42fc936f09847c5ec4127 and the result is the same
Seems like disabling -ffast-math did only fix the problem in 2D. I think @AndreaCatania knows it better here :)
Btw @David-Ochoa you don't need set_physics_process(true) and set_process(true) anymore since 3.0 ;)
For the reference, the same issue happens in 3.0.6. Test project: KinematicTest_3.0.zip
It happens with both Bullet and GodotPhysics backends.
Still reproducible in 3.2 beta 1 and current master branch (d596e16).
This is not a bug with Godot (or at least no longer a bug with Godot -- a lot of work has been done to fix RayShapes) so I think this issue can be closed.
The issue is caused by a flaw in the design of the controller used in the minimal example project. I've updated the minimal example project to more clearly show what is happening:
KinematicTest.zip
The move_and_slide() and move_and_slide_with_snap() take a Vector representing the velocity of motion and return a Vector representing the modified velocity in the event of a slide. This vector is perpendicular to the collision normal.
The Player KinematicBody has two CollisionShapes: a CapsuleShape and a RayShape. When moving along the floor or going up gentle slopes, the Player collides with the RayShape. When going up the steepest slope, the Player collides with the CapsuleShape.
When colliding with the RayShape, by design the collision normal is along the direction of the RayShape, not the normal of the surface of the object collided with. Since the RayShape is pointing along the y-axis, the perpendicular velocity Vector returned will be 0 in the y-direction. However, when colliding with the steepest slope, the Player collides with the CapsuleShape. Now the returned velocity Vector is perpendicular to the slope's normal, in a near vertical upwards direction.
The flaw in the minimal example project's controller is that it only uses the returned velocity Vector's y-value. With each physics step, the velocity Vector's x and z values are overwritten with values from the Input, and instantly reset to 0 when there is no Input. The velocity Vector's y-value is not overwritten, because the controller is also trying to simulate gravity by exponentially increasing the velocity in the y-direction using the previous value. This works as expected when moving along the floor or the gentle slopes, because the returned velocity Vector is perpendicular to the RayShape. The returned velocity Vector's y-value is 0 and the velocity in the y-direction is reset. However, when colliding with the steepest slope the returned velocity Vector is not zero in the y-direction, and the Player leaps into the air, or more specifically the slope redirects the player's velocity upwards. The result is unexpected, but correct.
Thanks for the answer, I have been working in other subjects but now I will modify the controller to address the issue.
But I have to add: I reported this as a bug because the examples in the official documentation use this approach and I thought Godot should handle this case. Maybe the examples need to be changed to avoid this confusion
Most helpful comment
Thanks for the answer, I have been working in other subjects but now I will modify the controller to address the issue.
But I have to add: I reported this as a bug because the examples in the official documentation use this approach and I thought Godot should handle this case. Maybe the examples need to be changed to avoid this confusion