Help me create State machine For my character

Godot 4.4

Could any help me make state machine? im still pretty new bad in coding :slight_smile:

extends CharacterBody2D

@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D
# list of Current States
enum States {IDLE, WALKING, RUNNING, FLYING, FLYFORWARD, INTERACTING, TALKING}
# This variable keeps track of the character's current state.
var state: States = States.IDLE
const SPEED = 300.0
const JUMP_VELOCITY = -400.0 
var flyf= false
var flip_h = false

func _ready():
	$AnimatedSprite2D.play("Idle")

func _physics_process(delta: float) -> void:
	# Add the gravity. and animtion for flying
	if not is_on_floor(): 
		velocity += get_gravity()  * delta
		#$AnimatedSprite2D.play("Flying")
	  

  # For player to Interact with other Objects
	if Input.is_action_just_pressed("Interact"):
		state == States.INTERACTING
		interacting = true
		$AnimatedSprite2D.play("Interact")
		for area in $InteractZone.get_overlapping_areas():
			if area.has_method("on_interact"):
				area.on_interact(self)
	else: state == States.IDLE

	# Handle Flying.
	
	if Input.is_action_just_pressed("Fly"):
		state == States.FLYING
		velocity.y = JUMP_VELOCITY
		animated_sprite.play("Fly")
		var direction = Input.get_axis("Walk Left", "Walk Right")
		# Trying to make if in FLying "not on floor" and press Left or RIght Animation play flying forward and character move 
	elif, not is_on_floor() Input.is_action_pressed("Walk Left") or Input.is_action_pressed("Walk Right"): # not working Error, EXPECTED conditional expression after Elif 
		state == states.FLYFORWARD:
		velocity.x = direction * SPEED
	elif, is_on_floor() and Input.get_axis("Walk Left", "Walk Right"): # not working same problem
		state == States.WALKING 
# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	if state == States.WALKING:
		var direction = Input.get_axis("Walk Left", "Walk Right")
		# for animation and coillsion fliping
		if direction:
			velocity.x = direction * SPEED
		else:
			velocity.x = move_toward(velocity.x, 0, SPEED)
		if Input.is_action_pressed("Walk Left"):
			$AnimatedSprite2D.flip_h = true
			$CollisionPolygon2D.scale.x = -1
			%CollisionShape2D.position.x = -261.0
		if Input.is_action_pressed("Walk Right"):
			$AnimatedSprite2D.flip_h = false
			$CollisionPolygon2D.scale.x = 1
			%CollisionShape2D.position.x = -41.0
	move_and_slide()

Hi,

“Making a state machine” is a very large topic to cover, so it’s hard to tell you “do this or that and everything will work”. Are you having any issue with your current code? Any bug, any architecture problem, anything? If so, please be a bit more specific about your issue.

If you’re looking for a general answer about state machines, I’d suggest you have a look at already existing resources:

Please note that I haven’t read/watched all of this resources, you may have to do your own researches and adapt to your project. But that should give you a basic idea of how to tackle state machines.

1 Like

honesty i wanna understand, how to Switch state and how it work, thx for video btw

There is no single way to make a state machine. You can use enums, dictionaries, or classes.

A state machine allows a single object or node to execute different behaviors, as if it were a completely different object.

To build a state machine, you need to define the states (as you already did with the enum), the functions associated with each state, and the transition rules.

When you change states, it’s like performing surgery on a human being and having them continue to function.

Here’s an example:

class_name StateMachine extends Node

# Set states

enum States {
	IDLE,
	MOVE,
	JUMP,
	DASH,
}

var current_state: States = States.IDLE

# Link states with functions by dictionary

var states: Dictionary = {
	States.IDLE: _idle_state,
	States.MOVE: _move_state,
	States.JUMP: _jump_state,
	States.DASH: _dash_state,
}

# Define function for each state

func _idle_state():
	print("Idle")
	pass

func _move_state():
	print("Move")
	pass

func _jump_state():
	print("Jump")
	pass

func _dash_state():
	print("Dash")
	pass


func _ready():
	
	states[States.IDLE].call()


func _process(delta: float) -> void:
	
	# Execute state code
	
	states[current_state].call()
	
	# Here, define the state transition rules, only change the current_state value
	
	var h = Input.get_axis("ui_left", "ui_right")
	
	if h > 0 or h < 0:
		current_state = States.MOVE
	else:
		current_state = States.IDLE

thanks this looks nice

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.