Decrease in speed causes weird character movement

Godot 4

Question

Hi all,

I’m trying to implement a slow decrease in speed for my CharacterBody2D. The goal is to let my character slide over slippery surfaces and to just have a feeling of the body having some weight to it. I can get it to work, but only when i’m not normalizing my velocity. Otherwise, my character is showing some weird movement behaviour.

For example, when i move left and right using button presses in a fast sequence, i can move left by keeping the right key pressed. It also spawns to different locations.

I suspect this is because for the physics engine there is a brief moment where the speed of one button press is applied to the speed of a different button press. And the change of direction is not proccessed yet or something alone those lines.

But i cannot figure out why this is happening. I have googled extensively and i have implemented multiple systems to handle the decrease in speed, based of internet examples. But what i currently have is the most basic system and i feel that it should work.

Here is my current code (i left it in a subpar state, don’t hate me. I’ve gone through dozens of iterations and am just experimenting at this point before i tidy anything up):

``````extends CharacterBody2D

@export var maxSpeed = 115
@export var runSpeed = 1.5 # multiplier
@export var acceleration:float = 10 # Lower is faster acceleration
@export var decceleration:float = 1.5 # Lower is faster decceleration

var currentSpeed = 0
var direction

func get_desiredSpeed(maxSpeed):
if currentSpeed < maxSpeed:
var accelSteps:float = maxSpeed / acceleration
#print('accelerating: ', currentSpeed, ' ', maxSpeed, ' ', acceleration, ' ', accelSteps)
currentSpeed = currentSpeed + accelSteps
#print('desiredSpeed_accel: ', currentSpeed)
return currentSpeed
elif currentSpeed >= maxSpeed and !Input.is_action_pressed("run"):
#print('desiredSpeed_max: ', currentSpeed)
currentSpeed = maxSpeed
return currentSpeed
elif currentSpeed >= maxSpeed and Input.is_action_pressed("run"):
#print('desiredSpeed_run: ', currentSpeed)
currentSpeed = maxSpeed * runSpeed
return currentSpeed

var directionX = Input.get_axis("left", "right")
var directionY = Input.get_axis("up", "down")

#print(currentSpeed)

if directionX:
currentSpeed = get_desiredSpeed(maxSpeed)
velocity.x = directionX
else:
#currentSpeed = 0
velocity.x = move_toward(velocity.x, 0, decceleration)
if directionY:
currentSpeed = get_desiredSpeed(maxSpeed)
velocity.y = directionY
else:
#currentSpeed = 0
velocity.y = move_toward(velocity.y, 0, decceleration)
if !directionY and !directionX:
currentSpeed = 0

print(currentSpeed)

velocity = velocity.normalized() * currentSpeed

print(velocity)

move_and_slide()

func _physics_process(delta):