Character sliding when turning around

Godot Version

v4.2.1.stable.official

Question

Hello, everyone. So the horizontal movement is set by using move_toward() functions for each direction and speed. The problem comes when you try to move in the opposite direction while the character is still reaching zero x velocity, since it is using move_toward() to accelerate, it has a significant slide effect because it is doing the move_toward function to go left for example while the move_toward function to go right is still working. So it ends up being faster in game to stop pressing inputs before you turn around allowing the character to come a quicker stop.
I thought of using a system where friction is added incrementally depending on current x speed but I completely know how to do that haha
any suggestions would be very appreciated, thank you

I’m not sure if I was clear but basically, if you press to move left or right, I used move_toward functions to accelerate and then if not pressing it uses move_toward to reach zero velocity. So for example, you press left and it accelerates you to a speed, then you let go and it decelerates you to zero, so if you press input to move in the opposite direction while the character is reaching zero velocity, the character will slide a lot because it is accelerating in the other direction but its takes longer because the initial velocity was going in the opposite direction rather than if the initial velocity was 0 then the behavior would seem normal. Thanks again

can you share your movement script

extends Node

var STATES = null
var Player = null

func enter_state():
pass
func exit_state():
pass
func update(delta):
return null

func player_movement(delta):
if Player.movement_input.x > 0:
Player.last_direction = 1
elif Player.movement_input.x < 0:
Player.last_direction = -1

if Player.is_on_floor():
	if Player.movement_input.x >0:
		#Player.velocity.x = Player.SPEED
		Player.velocity.x = move_toward(Player.velocity.x, Player.SPEED, Player.ACCELERATION * delta)
	elif Player.movement_input.x <0:
		#Player.velocity.x = - Player.SPEED
		Player.velocity.x = move_toward(Player.velocity.x, - Player.SPEED, Player.ACCELERATION * delta)
	else : 
		#Player.velocity.x = 0
		Player.velocity.x = move_toward(Player.velocity.x, 0, Player.FRICTION * delta)
	if Player.crouching:
		if Player.movement_input.x >0:
			Player.velocity.x = move_toward(Player.velocity.x, Player.CROUCH_SPEED, Player.CROUCH_ACCELERATION * delta)
		elif Player.movement_input.x <0:
			Player.velocity.x = move_toward(Player.velocity.x, - Player.CROUCH_SPEED, Player.CROUCH_ACCELERATION * delta)
		else : 
			Player.velocity.x = move_toward(Player.velocity.x, 0, Player.CROUCH_FRICTION * delta)
	elif Player.prone:
		if Player.movement_input.x >0:
			Player.velocity.x = move_toward(Player.velocity.x, Player.PRONE_SPEED, Player.CROUCH_ACCELERATION * delta)
		elif Player.movement_input.x <0:
			Player.velocity.x = move_toward(Player.velocity.x, - Player.PRONE_SPEED, Player.CROUCH_ACCELERATION * delta)
		else : 
			Player.velocity.x = move_toward(Player.velocity.x, 0, Player.CROUCH_FRICTION * delta)
else:
	if Player.movement_input.x >0:
		Player.velocity.x = move_toward(Player.velocity.x, Player.SPEED, Player.AIR_ACCELERATION * delta)
	elif Player.movement_input.x <0:
		Player.velocity.x = move_toward(Player.velocity.x, - Player.SPEED, Player.AIR_ACCELERATION * delta)
	else : 
		Player.velocity.x = move_toward(Player.velocity.x, 0, Player.AIR_FRICTION * delta)

its looks like a lot but its just different speeds and accelerations depending on certain booleans

you can make your deceleration always active

I think I was trying to do something similar earlier by making velocity.x *= friction but it wasn’t being incrementally added obviously. Do you mean I can have the velocity.x = move_toward(0 always running or something else?

yes, something like this

if Player.is_on_floor():
	if Player.movement_input.x >0:
		#Player.velocity.x = Player.SPEED
		Player.velocity.x = move_toward(Player.velocity.x, Player.SPEED, Player.ACCELERATION * delta)
	elif Player.movement_input.x <0:
		#Player.velocity.x = - Player.SPEED
		Player.velocity.x = move_toward(Player.velocity.x, - Player.SPEED, Player.ACCELERATION * delta)

	Player.velocity.x = move_toward(Player.velocity.x, 0, Player.FRICTION * delta)
	if Player.crouching:
		if Player.movement_input.x >0:
			Player.velocity.x = move_toward(Player.velocity.x, Player.CROUCH_SPEED, Player.CROUCH_ACCELERATION * delta)
		elif Player.movement_input.x <0:
			Player.velocity.x = move_toward(Player.velocity.x, - Player.CROUCH_SPEED, Player.CROUCH_ACCELERATION * delta)

		Player.velocity.x = move_toward(Player.velocity.x, 0, Player.CROUCH_FRICTION * delta)
	elif Player.prone:
		if Player.movement_input.x >0:
			Player.velocity.x = move_toward(Player.velocity.x, Player.PRONE_SPEED, Player.CROUCH_ACCELERATION * delta)
		elif Player.movement_input.x <0:
			Player.velocity.x = move_toward(Player.velocity.x, - Player.PRONE_SPEED, Player.CROUCH_ACCELERATION * delta)

		Player.velocity.x = move_toward(Player.velocity.x, 0, Player.CROUCH_FRICTION * delta)
else:
	if Player.movement_input.x >0:
		Player.velocity.x = move_toward(Player.velocity.x, Player.SPEED, Player.AIR_ACCELERATION * delta)
	elif Player.movement_input.x <0:
		Player.velocity.x = move_toward(Player.velocity.x, - Player.SPEED, Player.AIR_ACCELERATION * delta)

	Player.velocity.x = move_toward(Player.velocity.x, 0, Player.AIR_FRICTION * delta)

you might wanna double your speed since the fiction always active

it always comes down to simple is better lol, this solution works great, I just had to lower the friction and change the speed a little, thank you a ton

1 Like