Help from making a state sytem for running

Godot Version

4.7.1

Question

Can anyone help me with this code, programmed a run function for the the character but he only goes only one direction and doesn’t stop, and moves when hes not moving.

match active_state:
		State.idle:
			velocity.x = _direction * speed
			if _direction:
				$AnimatedSprite2D.flip_h = _direction < 0
			else:
				$AnimatedSprite2D.play("idle")
			if Input.is_action_just_pressed("jump"):
				active_state = State.jump
			if not is_on_floor():
				active_state = State.fall
			if Input.is_action_just_pressed("ui_run"):
				active_state = State.run
			if Input.is_action_just_released("ui_run"):
				active_state = State.idle
			if Input.is_action_just_pressed("dash") and _direction:
				switch_state(State.dash)
State.run:
			if _direction:
				$AnimatedSprite2D.play("run")
				$AnimatedSprite2D.flip_h = _direction < 0
			velocity.x += acceleration * _delta
			velocity.y += gravity * _delta
			if Input.is_action_just_released("ui_run"):
				switch_state(State.idle)
			if Input.is_action_just_pressed("jump"):
				switch_state(State.jump)
		State.run:
			$AnimatedSprite2D.play("walk")
			var _direction := Input.get_axis("ui_left", "ui_right")
			velocity.x = _direction * 1.5 * speed


Approximately like that

# the _direction is defined there, now you can access it from anywhere in that script.
@onready var _direction : float = 0.0

# other your code there

func _physics_process(delta: float) -> void:
	match active_state:
		State.idle:
			_idle(delta) # incapsualted to separated function
		State.walk:
			_walk(delta) # same as above
		State.run:
			_run(delta) # same as above

func _idle(delta: float) -> void:
	$AnimatedSprite2D.play("idle")
	if Input.is_action_just_pressed("dash"):
		switch_state("dash") 
		return
	if not is_on_floor():
		switch_state("fall")
		return
	# in case you want chang state to run 
	if Input.is_action_just_pressed("jump"):
		# not change state yourself, just add velocity to make it change to fall automatically.
		# if you need separated jump state you should add logic that runs on entering jump state.
		velocity.y += JUMP_IMPULSE
	# add input control in idle to determine when to change state to run
	_direction = Input.get_axis("ui_left", "ui_right")
	velocity.x = _direction * 1.5 * speed
	velocity.y += gravity * delta
	# use velocity instead of is_action_just_pressed()
	if velocity.x != 0:
		switch_state("run")
	
	
func _walk(delta: float) -> void:
	$AnimatedSprite2D.play("walk")
	# i suppose you want to let player dash from walk state ...
	if Input.is_action_just_pressed("dash"):
		switch_state("dash") 
		return
	# ... and in run state ...
	if Input.is_action_just_pressed("ui_run"):
		switch_state("run") 
		return
	# ... and in fall state
	if not is_on_floor():
		switch_state("fall")
		return
	# same as in previous func, changing direction while running
	_direction = Input.get_axis("ui_left", "ui_right")
	velocity.x = _direction * 1.5 * speed
	velocity.y += gravity * delta
	# when no input is given switching back to idle state
	if velocity.x == 0:
		switch_state("idle")


func _run(delta: float) -> void:
	$AnimatedSprite2D.play("run")
	if not is_on_floor():
		switch_state("fall")
		return
	if Input.is_action_just_pressed("jump"):
		velocity.y += JUMP_IMPULSE
		return
	# use sign() function to allow running in different directions
	velocity.x += sign(_direction) * acceleration * _delta
	velocity.y += gravity * _delta
	
	#returning to run state
	if not Input.is_action_pressed("ui_run"):
		switch_state(State.idle)
	
# rest of your code

Do you have several ‘run’ options in a single ‘match’ block? In that case only the first ‘run’ will work. The problem with continuing running happens because of you don’t zero direction and velocity neither in ‘idle’ state nor in ‘run’ state. Also you shadows ‘_direction’ in second ‘run’ block, if you want to change ‘_direction’ make it global and don’t use ‘var’ keyword in ‘run’ and change it not only in ‘run’ state, but also in ‘idle’ state.
Also i’d recommend not to use is_action_just_released() method everywhere, use current velocity to identify when you should switch states. For easier debugging and state programming i’d recommended to use ‘state charts’ plugin.

thank you.
i copied and pasted your code but i got errors

That looks like you pasted State.fall: line outside of match block. Check this match syntax ref: GDScript reference — Godot Engine (stable) documentation in English .