How to implement deceleration for reversing velocity/direction?

Godot Version

4.4.1-stable

Question

Hey all!

Implementing acceleration into a CharacterBody3D was fairly straightforward, using velocity.move_toward to accelerate towards a maximum speed, but how should I implement deceleration? In my case, I wanted my deceleration to be quite a bit more than my acceleration, for snappy movement, but without an instant.

My first thought was to simply use deceleration when the player is not holding an input, like this:

# dir is a Vector2 for input direction
# speed_sprint is my max speed in this context
if dir != Vector2.ZERO:
	velocity = velocity.move_toward(move_dir * speed_sprint, acceleration * delta)
else:
	velocity = velocity.move_toward(Vector3.ZERO, deceleration * delta)

Here, deceleration works properly when the player isn’t holding a direction, but what if they ARE holding a direction, it’s just a different one than they were before? For instance, let’s say the player is moving at max speed forwards, but suddenly changes to backwards? Because we ARE still holding a direction, this code applies the acceleration speed where the deceleration speed should probably be applied, resulting in slippery movement when changing directions.

Slipper movement demonstrated:
In this clip I got to full speed in one direction, then immediately reversed direction.

For checking if the player is reversing its direction, you will want to check if velocity and dir are pointing in opposite directions. You can do this with the dot product:

if dir.dot(velocity) < 0:
# deceleration

The dot product basically represents whether two vectors are pointing toward each other or away, as the section in the docs explains.
So everything in one piece would be:

# I swapped the two statements to make the final if-statement less cluttered
if dir == Vector2.ZERO or dir.dot(velocity) < 0:
	velocity = velocity.move_toward(Vector3.ZERO, deceleration * delta)
else:
	velocity = velocity.move_toward(move_dir * speed_sprint, acceleration * delta)

Note that this will only use the deceleration as long as the player is still moving in the opposite direction. As soon as they have started moving in the right direction, the acceleration will be used.

1 Like

Oh wow, that’s perfect! I suppose I should be reading the docs a bit more, haha. Thanks a ton!