Trying To Make A Momentum Based Movement System But The Crouch Bugs

Godot Version

Godot 4.6.2

Question

I’m Trying to make a momentum based movement system but the crouch system always bugs

Whenever I slide, My character tends to get axis locked and starts sliding parallel to the nearest axis after entering the slide state and won’t go in my looking direction

Enters Slide State
Goes In The Desired Direction (Looking Direction) As Expected
But Then Gets Aligned to the nearest axis

If you share code, please wrap it inside three backticks or replace the code in the next block:

extends CharacterBody3D


enum  State {   IDLE,
				MOVE,
				SPRINT,
				JUMP,
				FALL,
				SLIDE, }

@export_group("STATES")
@export var cur_state = State.IDLE



## PLAYER CAMERA ONREADY ##
@onready var neck = $Neck
@onready var camera_3d = $Neck/Camera3D

## CANVAS LAYER ONREADY ##
@onready var speed = $CanvasLayer/Speed


## TIMERS ONREADY ##
 ##JUMPBUFFER##
@onready var jumpbuffer = $Timers/JUMPBUFFER


## ABSTRACT VARIABLES ##
var direction: Vector3= Vector3(1,0,1)



## MOUSE SENSITIVITY ##
@export_group("MOUSE SENSITIVITY")
@export var mouse_sensi = 0.009


## PLAYER MOVEMENT VARIABLES (X-Z) ##
@export_group("MOVEMENT VAR (X-Z)")
######
@export var CUR_SPEED = 0.0
@export var use_speed = 0.0
######
@export var walk_speed = 12.0
@export var sprint_speed = 30.0

@export var slide_boost = 20.0

## ACCEL/DECEL ##
@export_group("ACCEL/DECEL")
@export var ground_accel = 100.0
@export var air_accel = 50.0
@export var decel = 80.0
@export var slide_decel = 10.0

## PLAYER MOVEMENT VARIABLES (Y) ##
@export_group("MOVEMENT VAR (Y)")
@export var JUMP_VELOCITY = 25.0
@export var gravity = -60.0




func _ready():
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _unhandled_input(event):
	if event is InputEventMouseMotion:
		
		rotate_y(-event.relative.x * mouse_sensi)
		
		camera_3d.rotate_x(-event.relative.y * mouse_sensi)
		
		camera_3d.rotation.x = clamp(camera_3d.rotation.x, deg_to_rad(-85), deg_to_rad(+80))
		
	if event.is_action_pressed("escape") and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
		Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
	elif event.is_action_pressed("escape") and Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
		Input.mouse_mode = Input.MOUSE_MODE_CAPTURED




func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += gravity * delta
		
	
	if Input.is_action_just_pressed("jump"):
		if is_on_floor():
			change_state(State.JUMP)
		elif not is_on_floor():
			jumpbuffer.start()
			
	if not jumpbuffer.is_stopped() and is_on_floor():
		change_state(State.JUMP)

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var input_dir = Input.get_vector("left", "right", "forward", "backward")
	direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	var current_speed = Vector2(velocity.x, velocity.z).length()
	
	
	match cur_state:
		State.IDLE:
			CUR_SPEED = 0.0
			
			velocity.x = move_toward(velocity.x,CUR_SPEED, decel * delta)
			velocity.z = move_toward(velocity.z,CUR_SPEED, decel * delta)
			if direction:
				if Input.is_action_just_pressed("sprint"):
					change_state(State.SPRINT)
				else:
					change_state(State.MOVE)
				
				
			elif not is_on_floor():
				change_state(State.FALL)
				
		State.MOVE:
			CUR_SPEED = move_toward(current_speed, walk_speed, ground_accel * delta)
			
			velocity.x = direction.x * CUR_SPEED
			velocity.z = direction.z * CUR_SPEED
			
			if Input.is_action_just_pressed("sprint"):
				change_state(State.SPRINT)
			
				
			elif direction == Vector3.ZERO:
				change_state(State.IDLE)
				
			elif not is_on_floor():
				change_state(State.FALL)
				
			
		State.JUMP:
			if velocity.y <= 0.0 or Input.is_action_just_released("jump"):
				change_state(State.FALL)
				
				
		State.FALL:
			if is_on_floor():
				if direction:
					change_state(State.SPRINT)
				
				else:
					change_state(State.IDLE)
					
		State.SPRINT:
			CUR_SPEED = move_toward(current_speed, sprint_speed, ground_accel * delta)
			
			velocity.x = direction.x * CUR_SPEED
			velocity.z = direction.z * CUR_SPEED
			
			if Input.is_action_just_pressed("sprint"):
				change_state(State.MOVE)
			elif direction == Vector3.ZERO:
				change_state(State.IDLE)
				
				
			elif not is_on_floor():
				change_state(State.FALL)
				
			if Input.is_action_pressed("crouch_slide"):
				change_state(State.SLIDE)
				
		State.SLIDE:
			
			
			
			velocity.x = move_toward(velocity.x, 0.0, slide_decel * delta)
			velocity.z = move_toward(velocity.z, 0.0, slide_decel * delta)
			
			if Input.is_action_just_released("crouch_slide"):
				change_state(State.SPRINT)
				
			if not is_on_floor():
				change_state(State.FALL)
			
	
	


	
		
	var flat_speed = Vector2(velocity.x, velocity.z).length()
	speed.text = "Speed: " + str(snappedf(flat_speed, 0.1))
		
	print(Vector2(velocity.x, velocity.z).length())

	move_and_slide()
	
func change_state(to_state: State):
	cur_state =to_state

	match cur_state:
		State.IDLE:
			pass
		
		State.MOVE:
			pass
			
		State.SPRINT:
			pass
			
		State.JUMP:
			velocity.y += JUMP_VELOCITY
			
		State.FALL:
			pass
			
		State.SLIDE:
			velocity.x += direction.x * slide_boost
			velocity.z += direction.z * slide_boost
	
	

Don’t use move_toward() for x and z separately, try Vector3.move_toward() instead.

			var target_velocity := Vector3(0.0, velcoity.y, 0.0)
			velocity = velocity.move_toward(target_velocity, slide_decel * delta)

I’ll Try This And Inform Youv