States not transitioning from Idle to Walk

Godot Version

Godot 4.0

Question

I recently learned about states and i followed a guide to the tee but i cannot figure out why my Player Idle state wont switch to Player Walk state

Heres the code for my PlayerIdle

extends State
class_name PlayerIdle
@onready var state_machine = $".."
@onready var player = $"../.."
@onready var player_animated = $"../../PlayerAnimated"
func Enter():
	player_animated.animation = "Idle"
	print("idle")

func Physics_Update(_delta: float):
	if player.velocity.x > 0:
		print("Hello")
		Transitioned.emit(self, "walk")

Here is my code for PlayerWalk

extends State
class_name PlayerWalk
@onready var state_machine = $".."
@onready var player = $"../.."
@onready var player_animated = $"../../PlayerAnimated"
func Enter():
	player_animated.animation = "Running"
	print("Walk")

func Physics_Update(_delta: float):
	if player.velocity.x == 0:
		print("Hi")
		Transitioned.emit(self, "idle")

This is my state machine:

extends Node

@export var initial_state : State

var current_state : State
var states : Dictionary = {}

func _ready():
	for child in get_children():
		if child is State:
			states[child.name] = child
			child.Transitioned.connect(_on_child_transition)
	if initial_state:
		initial_state.Enter()
		current_state = initial_state
func _process(delta):
	if current_state:
		current_state.Update(delta)
		
func _physics_process(delta):
	if current_state:
		current_state.Physics_Update(delta)
		
func _on_child_transition(_state, new_state_name):
	if State != current_state:
		return
		
	var new_state = states.get(new_state_name)
	if !new_state:
		return
	if current_state:
		current_state.Exit()
	new_state.Enter()
	current_state = new_state

Here is my state script:

extends Node
class_name State

@warning_ignore("unused_signal")
signal Transitioned

func Enter():
	pass
	
func Exit():
	pass
	
func Update(_delta: float):
	pass
	
func Physics_Update(_delta: float):
	pass

I am very confused and i also have this error:
W 0:00:02:0620 The signal “Transitioned” is declared but never explicitly used in the class.
UNUSED_SIGNAL
State.gd:4

I believe you got a warning that state was unused, so you marked it with a underscore to _state, but the solution is to use the variable; capitalization matters.

func _on_child_transition(state, new_state_name):
    if state != current_state:
        return

I’ve seen this tutorial on the forum before, I don’t think it’s necessary to run this check at all if you want to remove it.

I removed the thing that wasnt needed and capitalized State, it managed to break it even more

Invalid call. Nonexistent function ‘exit’ in base ‘Node (PlayerIdle)’.

Probably a similar capitalization issue, does your state script have func Exit()?

Yes it does, i changed all the variables so they match up but now some more errors pop up.

W 0:00:00:0353 The parameter “state” is never used in the function “_on_child_transition()”. If this is intended, prefix it with an underscore: “_state”.
UNUSED_PARAMETER
state_machine.gd:24

W 0:00:00:0353 The local variable “new_state” is declared but never used in the block. If this is intended, prefix it with an underscore: “_new_state”.
UNUSED_VARIABLE
state_machine.gd:28

If it helps i left out this code by mistake, its just a script that is referenced i believe

extends Node
class_name State

signal Transitioned

func Enter():
pass

func Exit():
pass

func Update(_delta: float):
pass

func _physics_process(_delta: float):
pass

Make sure to paste code with proper formatting,


Could you paste the whole _on_child_transition function again? Sounds like something has changed that I can’t keep track of.

I put _on_child_transition function back in and legit nothing changed but i will reformat all the stuff on the forum so its readable

Assuming this is up to date, the same issue we started with right? You want to use _state in this condition or remove it. You needed to un-capitalize State, the lowercase version is a variable, uppercase happens to be a Type.

func _on_child_transition(_state, new_state_name):
	#if _state != current_state: # or commented out
		#return

It no longer breaks but it keeps saying my transitioned signal isnt declared

It should be declared, it might warn that it’s unused but you can tell it to ignore that warning

@warning_ignore("unused_signal")
signal Transitioned

No more errors, the only problem is that the state is not switching over, i will update the code right now so that is accurate

That’s what this recommendation solves.

Do i want to make all of the State into _state ?

Nope, you have State which is a Type. Perfect, keep State around.

Then you have the function parameter _state which is a variable, let’s rename it to assumed_current_state and apply type notations, just for clarity.

func _on_child_transition(assumed_current_state: State, new_state_name: String) -> void:

Now we can compare this variable to another variable current_state

func _on_child_transition(assumed_current_state: State, new_state_name: String) -> void:
    if assumed_current_state != current_state:
        return

Since they can equal each other, this might not halt your function. But knowing this tutorial I think it’s a terrible comparison and you could remove it by commenting or just deleting the commented lines.

func _on_child_transition(_assumed_current_state: State, new_state_name: String) -> void:
    #if assumed_current_state != current_state:
        #return

Now the problem is that the signal itself isnt working, i can make a different post but ill try to figure this out, that you for the help