Finite State Machine issues

Godot Version

Godot_v4.2.2-stable_win64.exe

Question

I’m much new to the Game development/Godot space, in for about 3 weeks now though and I just got introduced to the Finite State Machine concept. There are 2 ways to implement it, the first is State Variable and the second is using State Pattern.

Trying to use the State Variable way for this small project I’m doing since it seems the easiest to implement, but I’m faced with an issue. It went well, but the character animation doesn’t change, it kept piling on top of each other instead.

For example, my character is playing Running and Idling animation simultaneously. Below is my code snippet:

extends CharacterBody2D


const SPEED = 100.0
const JUMP_VELOCITY = -300.0
@onready var player = $AnimatedSprite2D

# Player state
enum PLAYER_STATE {
	FALLING,
	IDLING,
	JUMPING,
	RUNNING
}

var current_state: int = PLAYER_STATE.IDLING

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")


func _ready():
	pass

func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += gravity * delta

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction = Input.get_axis("ui_left", "ui_right")
	if direction:
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	move_and_slide()
	
	# Flip character based on velocity
	if velocity.x > 1:
		player.flip_h = false
	elif velocity.x < -1:
		player.flip_h = true
	
	if direction == 1 || direction == -1:
		current_state = PLAYER_STATE.RUNNING
        else:
		current_state = PLAYER_STATE.IDLING
	
	match current_state:
		PLAYER_STATE.IDLING:
			player.play("Idle")
		PLAYER_STATE.RUNNING:
			player.play("Run")
		PLAYER_STATE.JUMPING:
			player.play("Jump")
		PLAYER_STATE.FALLING:
			player.play("Fall")

Check the following video to see visual examples too:

My question are:

1. How do I cleanup previous state so new state can play independently instead of playing together?

Any help will be greatly appreciated…

if direction == 1 || direction == -1:
	current_state = PLAYER_STATE.RUNNING
    # Added this line after posting this thread and the problem of playing two animations at the same time got solved, 
	#but is there any better to still implement state changes and cleanups?
else:
	current_state = PLAYER_STATE.IDLING

You can use animation tree, it is the best, you not need to use PLAYER_STATE variable

1 Like