Having Trouble implementing Coyote Time into my 2D platformer state machine

Godot Version

4.4 Stable

Question

I've been using an Enum-based state machine to build a new 2D Platformer Script for future projects and so far every state seems to work as intended: Floor detection, Movement, Jumping (+ Variable Jumping), and Falling. The only touble i'm having is implementing Coyote Time (I've implemented Coyote time into a non-statemachine sciprt before and it worked fine, but for some reason it's not working with my state machine no matter how much i try to tweak it).

extends CharacterBody2D

class_name CharacterStateMachine

enum STATE {FLOOR,JUMP,FALL

}

@export var SPEED : int = 100.0
@export var MAXSPEED : int = 100.0
@export var SPRINT: int = 300.0
@export var ACCEL : int = 10

var coyote_timer_activated: bool = false
var COYOTE_TIME: float = 2
var coyote_timer: float = 0.0

const JUMP_VELOCITY := -400.0
var GRAVITY := 1000.0

var active_state := STATE.FLOOR

func _physics_process(delta: float) → void:

var direction := Input.get_axis("move_left", "move_right")


#GROUNDED
if active_state == STATE.FLOOR:
	
	
	coyote_timer_activated = false
	coyote_timer = COYOTE_TIME
	
	if direction == 0:
		velocity.x = move_toward(velocity.x, 0, ACCEL)
	else: 
		velocity.x = move_toward(velocity.x, MAXSPEED * direction, ACCEL)
		
	if Input.is_action_pressed("Run"):
		
		MAXSPEED = SPRINT
		velocity.x = move_toward(velocity.x, MAXSPEED * direction, ACCEL)
	else:
		MAXSPEED = SPEED
		velocity.x = move_toward(velocity.x, MAXSPEED * direction, ACCEL)
		
	if not is_on_floor():
		
		print("falling")
		coyote_timer_activated = true
		active_state = STATE.FALL
		#active_state = 1
		
	
		
		
	if Input.is_action_just_pressed("jump") and (is_on_floor() or coyote_timer < COYOTE_TIME):
		
		print("JUMPED")
		
		
		active_state = STATE.JUMP
		
#JUMPED		
if active_state == STATE.JUMP:
	
	
	velocity.y = JUMP_VELOCITY
	
	
	velocity.x = move_toward(velocity.x, MAXSPEED * direction, ACCEL)
	

	
	
	
	active_state = STATE.FALL


	
		
#FALL
if active_state == STATE.FALL:
	
	
	coyote_timer -= delta
	coyote_timer_activated = true
	velocity.y += GRAVITY * delta
	velocity.x = move_toward(velocity.x, MAXSPEED * direction, ACCEL) 
	
	if Input.is_action_just_released("jump") and velocity.y < 0:
		print("jump release")
		velocity.y = JUMP_VELOCITY / 4
		
	
		
	
		
	
	if is_on_floor():
		
		print("grounded")
		
		coyote_timer_activated = false
		active_state = STATE.FLOOR
		coyote_timer = COYOTE_TIME

		
	
		
	
			
		
		
	
		
		
		
	
		
		
		
	
		
		
		
		
		
	
		
		
	
	
move_and_slide()

You need to check the jump button and coyote timer in your FALL state and perform the coyote jump from there.

Also, if your coyote_timer is counting downwards from COYOTE_TIME, to perform the jump you should check if its above 0 (and not if its below COYOTE_TIME). When jumping (for both regular jump and the coyote jump), you should set the timer to 0 to prevent multiple jumps.

You could not transition to fall state immediately when the character is not on floor. Only transition if the character is not on floor AND the coyote timer has run out.