First Person Movement along the wall makes the character move faster and glitches out a little.

The problem is pretty much visible here: https://youtu.be/_1dDdCSwVEo

Source: https://github.com/CryptoMares/FPS-Player-Controller

How would you fix it?

Thanks for your help!

UPDATE: Switching to JoltPhysics (https://github.com/godot-jolt/godot-jolt) seems to have eliminated the glitches at least.

  • \$\begingroup\$ The video doesn't clearly display increased speed when touching a wall. \$\endgroup\$
    – liggiorgio
    Commented Apr 30 at 10:07
  • \$\begingroup\$ True, but it does visibly increase, even though it doesn't register with velocity length. \$\endgroup\$
    – ThetaJones
    Commented Apr 30 at 11:12

2 Answers 2


enter image description here

When wish_dir passes through the wall, due to physical collision, the final velocity of the object in this frame will be parallel to the wall. What happens in this frame and next is:

  1. Use dot to find the projection of the current velocity to wish_dir, and make some restrictions on speed changes, and finally get add_speed.
  2. Use velocity + add_speed * wish_dir to get the velocity of the next frame(v2).
  3. This frame ends and the engine physics calculation is entered. Since v2 passes through the wall, the velocity component perpendicular to the wall is discarded.
  4. Go to the next frame. At this time velocity is v2', which is larger than v1.
  5. Calculate friction. This causes v2' to become smaller. When v2' is larger, the speed of reduction through friction is greater. When v2' becomes larger and larger each frame, at a certain moment, the acceleration effect of v2' will be offset by the friction force calculation, so that the object moves at a constant speed.

The fundamental problem is that max_velocity should be used to limit the final velocity rather than the length of the add_speed component during acceleration.

func accelerate(wish_dir: Vector3, max_velocity: float, delta):
    var add_speed = MAX_ACCELERATION * delta
    var new_velocity = velocity + add_speed * wish_dir
    new_velocity.y = 0
    var new_speed = min(new_velocity.length(),max_velocity)
    new_velocity = new_velocity.normalized() * new_speed
    new_velocity.y = velocity.y
    return new_velocity

As for the glitch, this problem also exists in the sample project:

enter image description here

  • \$\begingroup\$ This is very interesting, but it didn't didn't work unfortunately + it broke jump. Did it work perfectly on your end? In any case, thanks for taking the time. \$\endgroup\$
    – ThetaJones
    Commented Apr 26 at 13:57
  • \$\begingroup\$ @ThetaJones Yes, it works fine for me. You can use print(velocity.length()) to output and observe the speed, it will not exceed MAX_VELOCITY_GROUND. \$\endgroup\$
    – Mangata
    Commented Apr 26 at 14:58
  • \$\begingroup\$ What about those small glitches? (See: youtu.be/_1dDdCSwVEo) Are they gone too on your end? \$\endgroup\$
    – ThetaJones
    Commented Apr 26 at 15:10
  • \$\begingroup\$ @ThetaJones Yes, those glitches also hapen to me. And I think it's a internal bug in move_and_slide because when I try to change the collision shape to BoxShape3D, they just disapeared. \$\endgroup\$
    – Mangata
    Commented Apr 26 at 16:08
  • 1
    \$\begingroup\$ FYI: Jolt Physics fixed the glitchiness. \$\endgroup\$
    – ThetaJones
    Commented Apr 26 at 19:50
var current_speed = velocity.normalized().dot(wish_dir)

velocity should be normalized before dot product

  • \$\begingroup\$ Thanks, but this does not fix the problem though. It's still going faster along the wall and there are still these micro-glitches. \$\endgroup\$
    – ThetaJones
    Commented Apr 26 at 8:05
  • \$\begingroup\$ @ThetaJones i did try it in godot and when the vel was not normalized it was obvious by printing the vel that it indeed gets bigger along the wall it doesn't happen when vel is normalized \$\endgroup\$ Commented Apr 26 at 10:37
  • \$\begingroup\$ But did you see the video that demonstrates the problem? That's what I would like to fix, pretty much. \$\endgroup\$
    – ThetaJones
    Commented Apr 26 at 13:58
  • \$\begingroup\$ yes is did that before cloning the repo though I'm pretty sure @mangata answer works better \$\endgroup\$ Commented Apr 26 at 15:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .