#State machine transition isnt working

14 messages · Page 1 of 1 (latest)

whole wagon
#

my state transition isnt working and im not really sure why i thought i set up everything?? im still very new to state machines

#

this is my base state class

#

the fsm

#

the idle state

#

and the run state

#

i would also like help with how to get movment working on the run state since im extending from state i dont have the code to work with velocity.x or is_on_floor functions unless im wrong

#

also if my terminlogy is wrong its cause im still new

loud spindle
#

Glancing over the code it seems that at the moment nothing really runs, except the _ready() function of your FiniteStateMachine class and then the .Enter() function of the initial_state.

Running stuff each Frame

If you want to run code each frame then you need a _physics_process() and/or _process() somewhere inside the FiniteStateMachine class.
In the State you don´t want to overwrite_physics_process() and/or _process() directly, because then each state would just run all the time each frame. Instead you have some function like update() or physics_update() that you define that you will call inside _process() of the FiniteStateMachine. The Statemachine only lets the current_state run each frame then.

From your State Class it seems like the Update() function could be something that you want to run each frame.
That means in your FiniteStateMachine script you´d have something like this:

extends Node
class_name FiniteStateMachine
...
var current_state:State
...
func _ready():
    ...

func change_state(...):
   ...

func _process(delta: float):
    current_state.Update(delta)

Another thing i noticed is, that your State class has the 3 functions Enter(), Exit() and Update(), but not the function _physics_process_update() that you defined in the run state. I guess this is the function that you want to run periodically inside with _physics_process.
Then i would add that function definition inside your State class and add the line to run it inside the Statemachine too.

# // fsm.gd
extends Node
class_name FiniteStateMachine
...

func _physics_process(delta: float):
    current_state._physics_process_update(delta)
#

If you want a certain type/class of State to run inside the Statemachine, id have them use all the same interface (the same function names), because in the end the Statemachine will dictate which functions the states call each frame. And if it doesnt know how they are called or they are called differently, youll have some troubles.

Making the character move

To make the Character move you need to have a reference to it.
I can recommend this tutorial: (https://www.gdquest.com/tutorial/godot/design-patterns/finite-state-machine/)
In their PlayerState class they get a reference with player = owner as Player.
If the Player node is the root of the scene, then it is the owner of your State Node in this case, so it is one easy way to get a reference to it.
With type casting usingas Player , you´ll get the autocompletion of all the properties and methods of your Characterbody2D (and the rest of the Player class).

You can then move the player inside your State with player.move_and_slide() or anything.

class_name PlayerState extends State
...

var player: Player

func _ready() -> void:
    await owner.ready
    player = owner as Player

Instead of using owner you could let the Statemachine script give its children (the States) a reference to the player/character node (same place where you connect the signals etc.).

Note: In their tutorial PlayerState is just a new generic type of State which has the same interface, but just the player reference added. They then extend from that PlayerState for their Idle, Run etc. state.
You can implement all that stuff with the reference inside your State class instead and extend the States like you do it right now anyway if you want.

loud spindle
#

But to actually answer the question about the transition in a tldr way:

  • Your current state is the IdleState where you want to start transition into the Run state inside the Update() function by checking for an Input
  • Your transition doesnt work , since you never call Update() anywhere
  • You want to call it inside _process() inside your FiniteStatemachine, where you´ll run the current_state.Update(delta)