• Godot Help
  • move_and_slide causing infinite sliding when on surface

Hi all,

New to Godot here, so apologies for anything obvious I'm missing here.

I'm creating a movement system for a 2.5D RPG, similar to Paper Mario. Currently, I have a system set up that uses acceleration and deceleration when moving, along with a sprint mechanic, and a "skidding" mechanic. The skidding occurs when the player attempts to take a sharp turn, locking them into their current direction, whilst decelerating until they've completely stopped, then allowing them to move again. This system was working as intended before implementing gravity and vertical movement - however, now if the player takes turns in certain directions, or skids whilst sprinting, they will continue to skid indefinitely, with their speed never reaching zero.

Here's the code:

extends KinematicBody

#Variable Declarations
var walkSpeed = 6.0
var sprintSpeed = 11.0
var maxSpeed
var acceleration = 20.0
var deceleration = 30.0
var velocity = Vector3()
var direction = Vector2()
var input_direction = Vector2()
var state = "walking"
var turnSpeed = 10.0
var fallSpeed = 30.0
var jumpSpeed = 10.0

func _physics_process(delta):
	var currentSpeed = velocity.length()
	
	#jumping
	if Input.is_action_just_pressed("jump"):
		velocity.y = jumpSpeed
	
	#Movement
	maxSpeed = walkSpeed
	if state == "walking":
		if Input.is_action_pressed("sprint"):
			maxSpeed = sprintSpeed
		
		#Get input direction
		input_direction.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up")
		input_direction.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
		input_direction = input_direction.normalized()
		
		#Instantly set direction if player is not moving (no turning)
		if currentSpeed == 0:
			direction = input_direction
		direction = (direction.linear_interpolate(input_direction, turnSpeed * delta)).normalized()
		
		#Detect if player takes a sharp turn, and skid if so
		if abs(direction.angle_to(input_direction)) > PI/2:
			state = "skid"
			if currentSpeed > walkSpeed:
				state = "sprintskid"
		
		#Stop if no input
		if input_direction.length() > 0:
			currentSpeed += acceleration * delta
		else:
			currentSpeed -= deceleration * delta
			
	#Skidding
	if state == "skid":
		currentSpeed -= deceleration * delta * 2
		if currentSpeed <= deceleration * delta * 2:
			#When speed reaches zero, return to normal state
			currentSpeed = 0
			state = "walking"
	#Sprint Skidding
	if state == "sprintskid":
		currentSpeed -= deceleration * delta * 0.35
		if currentSpeed <= deceleration * delta * 0.35:
			#When speed reaches zero, return to normal state
			currentSpeed = 0
			state = "walking"
	
	
	currentSpeed = clamp(currentSpeed, 0, maxSpeed)
	velocity.x = direction.x * currentSpeed
	velocity.z = direction.y * currentSpeed
	move_and_slide(velocity, Vector3.UP)
	
	#Jump sound
	if Input.is_action_just_pressed("jump"):
		$AudioStreamPlayer2D.play()
	#sprite code
	if currentSpeed > 0:
		if velocity.x < 0.1:
			$Spriteholder/AnimatedSprite3D.play("run")
			$Spriteholder/AnimatedSprite3D.scale.x = -1
		if velocity.x > -0.1:
			$Spriteholder/AnimatedSprite3D.play("run")
			$Spriteholder/AnimatedSprite3D.scale.x = 1
	else:
		$Spriteholder/AnimatedSprite3D.play("stand")
	if state == "skid" or state == "sprintskid":
		$Spriteholder/AnimatedSprite3D.play("skid")
	
	if is_on_floor():
		velocity.y = 0
	else:
		velocity.y -= fallSpeed * delta

Here's some footage.

Thanks in advance.

  • Never mind. Was being stupid.
    var currentSpeed = velocity.length() needed to be var currentSpeed = Vector2(velocity.x, velocity.z).normalized()
    Sorry for timewasting.

Absolutely didn't understand formatting code blocks here, apologies. Still, it should be readable enough.

    Never mind. Was being stupid.
    var currentSpeed = velocity.length() needed to be var currentSpeed = Vector2(velocity.x, velocity.z).normalized()
    Sorry for timewasting.

    Sometimes the best way to solve a problem is to show others and talk yourself through it. Done that plenty of times myself.

      uckersSket Absolutely didn't understand formatting code blocks here, apologies. Still, it should be readable enough.

      I've fixed it. for a code block make sure the 'tags' are ``` rather than ` and each on a new line.

      abizrihays Sometimes the best way to solve a problem is to show others and talk yourself through it. Done that plenty of times myself.

      Also known as rubberducking.