Godot state machine 2D

Godot Version

Godot 4

Question

Hi, I’m a little confused, I’m new to programming and I’m currently replacing the default player script with a statemachine script,

However, when I jump the player will get stuck mid air. Obviously this isn’t working as intended, however I can’t actually see the problem myself, I hope someone can help and I apologise in advance for my noobish replies( I may ask questions)

Please see below my script

State player Script
extends CharacterBody2D

var movement_speed : float = 130
var jump_velocity = -300
var player_direction : Vector2

@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D

enum States { IDLE, MOVE, JUMP, DASH, DEATH }
var currentState = States.IDLE

func _physics_process(delta: float) -> void:
	if not is_on_floor():
		velocity += get_gravity() * delta

	
	handle_state_transitions()
	peform_state_actions(delta)
	move_and_slide()

func handle_state_transitions():
	if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right"):
		currentState = States.MOVE
	else:
		currentState = States.IDLE
		
	if Input.is_action_just_pressed("jump") and is_on_floor():
		currentState = States.JUMP

func peform_state_actions(delta):
	match currentState:
		States.MOVE:
			player_direction.x = Input.get_axis("move_left", "move_right")
			if movement_speed > 0:
					$AnimatedSprite2D.animation = "run"
			player_direction = player_direction.normalized()
			print("MOVE")
			if player_direction.x < 0:
				$AnimatedSprite2D.flip_h = true
			else:
				if player_direction.x > 0:
					$AnimatedSprite2D.flip_h = false
		
			velocity = player_direction * movement_speed
		
		States.IDLE:
			velocity = velocity.move_toward(Vector2.ZERO, movement_speed) * delta
			$AnimatedSprite2D.animation = "idle"
			print("IDLE")
		
		States.JUMP:
			if is_on_floor():
				velocity.y = jump_velocity
			print("jumping")
			
		States.DEATH:
			pass

TIA

You are overwriting the velocity from gravity in every state. You might need to reorganize your code a bit.

Ahh thank you.

I have made some changes to my code as can be seen below.

How would I go about handling the jump now? Because no matter what I done with the jump it just wasn’t working. So I sorted the code a little bit better(imo)

Player State Machine

extends CharacterBody2D

var movement_speed : float = 130
var JUMP_VELOCITY = -300
var direction : Vector2
@onready var timer: Timer = $Timer

@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D

enum States { IDLE, MOVE, JUMP, DASH, DEATH }
var currentState := States.IDLE

func changestate(newState):
currentState = newState

func _physics_process(delta: float) → void:
if not is_on_floor():
velocity.y += get_gravity().y * delta
direction.x = Input.get_axis(“move_left”, “move_right”)
if direction:
velocity.x = direction.x * movement_speed
else:
velocity.x = move_toward(velocity.x, 0, movement_speed)
match currentState:
States.IDLE:
idle()
States.MOVE:
move()
States.JUMP:
jump()
States.DASH:
dash()
States.DEATH:
death()
print (get_gravity())

func jump():
pass
func move():
animated_sprite.play(“run”)
if direction.x < 0:
animated_sprite.flip_h = true
if direction.x > 0:
animated_sprite.flip_h = false
velocity = direction * movement_speed
move_and_slide()
if direction == Vector2.ZERO:
changestate(States.IDLE)
return
print(“moving”)

func idle():
velocity = Vector2.ZERO
if direction != Vector2.ZERO:
changestate(States.MOVE)
animated_sprite.play(“idle”)
print(“IDLE”)

func dash():
pass

func death():
pass