FPS controller, problem with transitioning between states

Godot Version

v4.6.1.stable.official [14d19694e]

Question

Im trying to set up FPS controller. Here is the problem: I set up a scene with a tunnel I can access only if Im crouching or sliding into it. When Im crouch walking into it everything is fine. But when Im running and then sliding into this tunnel a problem emerges. If I hold crouch at the end of a slide I transition into crouching state so everything is fine, but if Im not holding “crouch“ button at the end of my slide Im ending up in a position where I still in the tunnel and my collision is, as expected, crouching collision, but the speed at which I move is running speed as if Im standing, and camera position end up, as expected, at crouching level, but slightly higher than it supposed to be, as if its stuck inbetween. First thing that came to mind is to abandon this mess and to set up a proper state machine with clear transitions between separate states, but Im not knowledgeable enough to do it at the moment. Im basically learning engine and programming as I go and simple boolean operations is as far as my knowledge goes. So how do I fix it within my current framework?

Here is my code:

extends CharacterBody3D


var RUNNING : bool = false
var WALKING : bool = false
var CROUCHING : bool = false
var SLIDING : bool = false
var JUMPING : bool = false

var input_dir : Vector2 = Vector2.ZERO
var direction : Vector3 = Vector3.ZERO
var current_speed : float = 0.0
var last_velocity : Vector3 = Vector3.ZERO

@export_group("Movement Variables")
@export var GRAVITY : float = 20.0
@export var JUMP_VELOCITY : float = 7.5
@export var CROUCH_DEPTH : float = 0.8

@export_group("Speed Variables")
@export var RUN_SPEED : float = 7.2
@export var WALK_SPEED : float = 3.6
@export var CROUCH_SPEED : float = 3.6

@export_group("Slide Variables")
@export var SLIDE_SPEED : float = 7.2
@export var SLIDE_TIMER_MAX : float = 0.6
var slide_timer : float = 0.0
var slide_vector : Vector2 = Vector2.ZERO

@export_group("Other Variables")
@export var SENSITIVITY : float = 0.001
@export var LERP_SPEED : float = 8.0
@export var AIR_LERP_SPEED : float = 2.0


func _ready() -> void:
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
		
		
func _physics_process(delta: float) -> void:
	if not is_on_floor():
		velocity.y -= GRAVITY * delta
		
	input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
		
	#JUMPING
	if Input.is_action_just_pressed("jump") and is_on_floor():
		velocity.y = JUMP_VELOCITY
		%CameraAnimPlayer.play("Jump")
		
		self.rotation.y += %CameraHandler.rotation.y
		%CameraHandler.rotation.y = 0.0 #I need this so at the end of the slide CharacterBody3D y rotation wont be displaced relative to camera's y rotation
		
		RUNNING = false
		WALKING = false
		CROUCHING = false
		SLIDING = false
		JUMPING = true
		
		
	#Handles landing
	if is_on_floor():
		if last_velocity.y < -15.0:
			%CameraAnimPlayer.play("JumpLandingHeavyBob")
			print(last_velocity.y)
		elif last_velocity.y < -4.0:
			%CameraAnimPlayer.play("JumpLandingBob")
			print(last_velocity.y)
		
	#CROUCHING
	if Input.is_action_pressed("crouch") or SLIDING:
		%StandCollisionShape.disabled = true
		%CrouchCollisionShape.disabled = false
		
		current_speed = lerp(current_speed, CROUCH_SPEED, delta * LERP_SPEED)
		%CameraHandler.position.y = lerp(%CameraHandler.position.y, 1.5 - CROUCH_DEPTH, delta * LERP_SPEED)
			
		#Slide begin logic
		if RUNNING and input_dir != Vector2.ZERO and is_on_floor():
			SLIDING = true
			slide_timer = SLIDE_TIMER_MAX
			slide_vector = input_dir
			print("SlideBegin")
			
		RUNNING = false
		WALKING = false
		CROUCHING = true
		JUMPING = false
		
		
	elif !%CanStandCheck.is_colliding():
		#Standing
		%StandCollisionShape.disabled = false
		%CrouchCollisionShape.disabled = true
		
		%CameraHandler.position.y = lerp(%CameraHandler.position.y, 1.5, delta * LERP_SPEED)
		
		if Input.is_action_pressed("run") and is_on_floor():
			#Walk/run (sorry for confusing mess, its flipped for now cause I want to be running by default)
			current_speed = lerp(current_speed, WALK_SPEED, delta * LERP_SPEED)
			
			self.rotation.y += %CameraHandler.rotation.y
			%CameraHandler.rotation.y = 0.0
			
			RUNNING = false
			WALKING = true
			CROUCHING = false
			SLIDING = false
			JUMPING = false
			
			
		else:
			current_speed = lerp(current_speed, RUN_SPEED, delta * LERP_SPEED)
			
			self.rotation.y += %CameraHandler.rotation.y
			%CameraHandler.rotation.y = 0.0
			
			RUNNING = true
			WALKING = false
			CROUCHING = false
			SLIDING = false
			JUMPING = false
			
			
	#Handles SLIDING
	if SLIDING:
		slide_timer -= delta
		if not Input.is_action_pressed("crouch") or slide_timer <= 0.0:
			SLIDING = false
			self.rotation.y += %CameraHandler.rotation.y
			%CameraHandler.rotation.y = 0.0
			print("SlideEnd")
		
		
	#Horizontal walk bob logic
	if input_dir != Vector2.ZERO:
		play_walk_bob_anim()
	else:
		%WalkBobAnimPlayer.pause()
		
		
	# Get the input direction and handle the movement/deceleration.
	if is_on_floor():
		direction = lerp(direction, (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),
		delta * LERP_SPEED)
	else:
		if input_dir != Vector2.ZERO:
			direction = lerp(direction, (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),
			delta * AIR_LERP_SPEED)
		
	if SLIDING:
		direction = (transform.basis * Vector3(slide_vector.x, 0, slide_vector.y)).normalized()
		current_speed = (slide_timer + 0.9) * SLIDE_SPEED
		
	if direction:
		velocity.x = direction.x * current_speed
		velocity.z = direction.z * current_speed
		
	#Last velocity is used to determine that player landed after a jump so it can play landing anim
	last_velocity = velocity
	
	move_and_slide()
	
	
#Mouse look logic
func _unhandled_input(event: InputEvent) -> void:
	if event is InputEventMouseMotion:
		if SLIDING:
			%CameraHandler.rotation.y = %CameraHandler.rotation.y - event.relative.x * SENSITIVITY
			%CameraHandler.rotation.x = %CameraHandler.rotation.x - event.relative.y * SENSITIVITY
			%CameraHandler.rotation.x = clamp(%CameraHandler.rotation.x, deg_to_rad(-90), deg_to_rad(90))
		else:
			rotation.y = rotation.y - event.relative.x * SENSITIVITY
			%CameraHandler.rotation.x = %CameraHandler.rotation.x - event.relative.y * SENSITIVITY
			%CameraHandler.rotation.x = clamp(%CameraHandler.rotation.x, deg_to_rad(-90), deg_to_rad(90))
			
			
#For horizontal walk bob
func play_walk_bob_anim() -> void:
		if RUNNING and is_on_floor():
			%WalkBobAnimPlayer.play("WalkBob")
			%WalkBobAnimPlayer.speed_scale = 1.0
		elif WALKING and is_on_floor():
			%WalkBobAnimPlayer.play("WalkBob")
			%WalkBobAnimPlayer.speed_scale = 0.75
		elif CROUCHING and is_on_floor():
			%WalkBobAnimPlayer.play("WalkBob")
			%WalkBobAnimPlayer.speed_scale = 0.5
		else:
			%WalkBobAnimPlayer.pause()