Godot: move_and_slide() causes jitter when colliding with corners

Created on 17 Sep 2019  Â·  13Comments  Â·  Source: godotengine/godot

Godot version:
3.1.1.stable.official

OS/device including version:
Linux / Fedora 30

Issue description:
move_and_slide() can cause a lot of jitter when KinematicBody collides with corners, or anything actually. (sometimes even with simple 90° corners)

You can observe this in pretty much every single project that uses move_and_slide(), including the FPS Tutorial from Godot documentation.

Notes:

  • Choosing GodotPhysics instead of Bullet may reduce the jitter, but it's still there and visible.
  • I haven't tested other move* functions.

Steps to reproduce:

  • Use move_and_slide().
  • Collide with some corners.

Minimal reproduction project:
godot-fps-master.zip

bug confirmed physics

Most helpful comment

Hello there, I can confirm that this still occurs in v3.2 Alpha 2. As a side note, calling move_and_slide*() on each separate axis can help mitigate the issue like so:

vel.x = move_and_slide_with_snap(Vector3(vel.x, 0.0, 0.0), snap, Vector3.UP, true, 1).x vel.y = move_and_slide_with_snap(Vector3(0.0, vel.y, 0.0), snap, Vector3.UP, true, 1).y vel.z = move_and_slide_with_snap(Vector3(0.0, 0.0, vel.z), snap, Vector3.UP, true, 1).z

As a side effect, the player unfortunately slides more slowly along walls and the jittering is only reduced when using Bullet instead of GodotPhysics using this method. It's also a pretty ugly hack.

As far as using move_and_slide() as it was intended went, I tested this with reasonably complex CSG constructs and level geometry I made in Blender and the jitter occurs only with these, further corroborating @narcissawright's claim that it never happens with convex shapes.

kinematicbody-plus-demo.zip

Here is a demonstration project that contains a simple CSG "garage" (the one immediately in front of the player in the scene). Moving into the corner produces jitter, but the “towers” behind the player, which are ordinary convex BoxShapes, do not produce jitter when moving into the corner.

All 13 comments

I can confirm this. This is the reason I switched to rigid body physics instead.

Yes, this is a problem of capsule collision shape and sphere shape.
Never worked properly as far I remember.

For now you may consider using a cylinder or a box shape with a ray shape at the bottom with length of the maximum step height your character can climb.

I might be wrong, but I think jitter happens with a box shape too. (need to test this properly)

Yep, looks like it's happening with a box shape as well.

I think this only happens with tri-mesh collisions, putting two seperate box collision shapes and making a corner doesn't produce jitter

This is an issue for me as well. It is especially apparent in corners, but it also happens on walls. It doesn't seem to happen with simple convex shapes (like the grey rectangle in the attached gif).

problem

Hello there, I can confirm that this still occurs in v3.2 Alpha 2. As a side note, calling move_and_slide*() on each separate axis can help mitigate the issue like so:

vel.x = move_and_slide_with_snap(Vector3(vel.x, 0.0, 0.0), snap, Vector3.UP, true, 1).x vel.y = move_and_slide_with_snap(Vector3(0.0, vel.y, 0.0), snap, Vector3.UP, true, 1).y vel.z = move_and_slide_with_snap(Vector3(0.0, 0.0, vel.z), snap, Vector3.UP, true, 1).z

As a side effect, the player unfortunately slides more slowly along walls and the jittering is only reduced when using Bullet instead of GodotPhysics using this method. It's also a pretty ugly hack.

As far as using move_and_slide() as it was intended went, I tested this with reasonably complex CSG constructs and level geometry I made in Blender and the jitter occurs only with these, further corroborating @narcissawright's claim that it never happens with convex shapes.

kinematicbody-plus-demo.zip

Here is a demonstration project that contains a simple CSG "garage" (the one immediately in front of the player in the scene). Moving into the corner produces jitter, but the “towers” behind the player, which are ordinary convex BoxShapes, do not produce jitter when moving into the corner.

Duplicate of #29392?

I confirm that this problem is still present in the 3.2rc1. @Calinou I think is a big problem, can we label it to be fixed in this milestone? Now if you have a simple 3d platform if you stay between 2 perfect aligned static platforms you will see this jittering and is frustrating to fix this issue.

@grevius5 We need more information before we can look into fixing this. It'd be worth testing whether this issue occurs in Godot 3.0 (and to a lesser extent, 2.1). If the bug doesn't occur in those versions, you could then look into bisecting the commit where the bug started appearing. This requires building the engine from source many times, but it should be entirely feasible.

In the meantime, I wonder if lawnjelly's smoothing-addon can be used to make the bug less noticeable.

@Calinou you may be aware of this already (apologies if you are) but in #34596, @madmiraal provided some greatly needed specificity and cited this PR as the point at which the jittering started to appear in GodotPhysics and Bullet respectively. Do you think it could lend sufficient insight to the team?

I had this problem in a 3D platformer I was making. When a character (a kinematic body) ran along a set of boxes (static objects) 1 unit high, my character's Y-coordinate would oscillate between 1.06 and 1.10 as they crossed a corner. For a character 1 unit high, this results in the camera jittering up and down by 4% everytime they crossed a boundary.

I worked around the issue by scaling every object in my game by a factor of 1,000%. The jitter is still about 0.04, but when the objects are 10x bigger it's harder to notice.

The small amount of jitter remaining after my previous fix (scaling everything up 1,000%) was still bothering me, so I came up with a second fix which removes the remaining jitter. Here's my new gravity function.

func _apply_gravity(delta: float) -> void:
    _velocity += Vector3.DOWN * 400.0 * delta

    # If acceleration via gravity makes our momentum something small like -6, there's a risk we won't actually collide
    # with the surface we're sitting on which causes causing an unpleasant jitter effect.
    if _velocity.y < 0.0 and _velocity.y > -10:
        _velocity.y = -10

The jitter occurs because the Y velocity is a small number like -6, which is too slow for Godot to detect a collision in some cases. Then the Y velocity increases to something faster like -13 and Godot detects a collision. It alternates between these states every other frame, causing the jitter

With this if statement I've added, the Y velocity is never a small number like -6, so Godot always detects a collision. You can adjust the '-10' value based on what works for you.

Was this page helpful?
0 / 5 - 0 ratings