Designer-friendly Finite State Machine implemented in "Godotic" way
This version is only compatible with Godot 4.x, check out godot3 branch for older version
Designer-friendly
Design
StateMachine
in a flowchart-like editor
Remote Debug
Visualize flow of
StateMachine
& inspect parameters in realtime
Self-explanatory
Visualize game/UI state from flowchart
Zero learning curve
Similar workflow as using
AnimationTree
, and not required to inherit any custom class, just plug and play
Nested FSM
Nested Finite State Machine workflow supported to create complex state machine with ease
Reusability
As a
Resource
,StateMachine
can be used repeatedly in different scenarios(StateMachinePlayer
) and provide different outcome based on the input.
Minimal
Compact data structure for
StateMachine
resource file
For more detail, see CHANGELOG.md
or
Download this respository, move addons/imjp94.yafsm
to your {project_dir}
Enable it from Project -> Settings -> Plugins
or
plug("imjp94/gd-YAFSM")
Add StateMachinePlayer
node from "Create New Node" window.
Select created node and the state machine editor should shows up.
Click on "Create StateMachine" button to get started.
Finally, Right-Click
on graph to add state node and Shift + Drag
on node to start connect(Shift + Drag
again on line to reconnect)
Special states:
StateMachine
, always requiredState
that break the flow of StateMachine
, unless restarted with StateMachinePlayer.restart()
, mainly used in nested-StateMachine
.After setup StateMachine
with editor, you can connect to the following signals from a StateMachinePlayer
:
transited(from, to)
: Transition of stateupdated(state, delta)
: Time to update(defined by process_mode
), up to user to handle anything, for example, update movement of KinematicBody
Example code snippet of KinematicBody connect "updated" signal
And control StateMachinePlayer
by accessing parameter:
var smp = get_node("StateMachinePlayer")
smp.set_trigger("jump")
smp.set_param("jump_count", 1)
smp.get_param("on_floor", false)
smp.has_param("velocity")
That's it!
For most of the case, you don't have to inherit from any custom class by this plugin, simply just connect signals to your existing node and you're good to go.
See documentation for more details
The only different between nested/normal FSM is how state/parameters are accessed.
var normal_state = "Idle"
var nested_state = "App/Game/Play" # EndState can be Entry/Exit
StateDirectory
class is provided to traverse state path like file directory:
const StateDirectory = preload("addons/imjp94.yafsm/src/StateDirectory.gd")
# Handle "transited" signal
func _on_normal_state_transited(from, to):
match to:
"Entry":
print("Enter")
"Game":
print("Game")
"Exit":
print("Exit")
# Handle "transited" signal
func _on_nested_state_transited(from, to):
var to_dir = StateDirectory.new(to)
match to_dir.next(): # Initial next() required to move to base state
"Entry":
print("Enter")
"Game":
match to_dir.next(): # It can be called recursively, until return null
"Entry":
print("Game Enter") # Game/Entry
"Exit":
print("Exit")
Behind the scene, StateMachinePlayer
always differentiate parameters into 2 types: global & local
erase_param
/clear_param
called by uservar smp = get_node("StateMachinePlayer")
var global_param = smp.get_param("state")
var local_param = smp.get_param("App/Game/playing")
local_param = smp.get_nested_param("App/Game", "playing")
smp.set_param("App/Game/End/victory", true)
smp.set_nested_param("App/Game", "paused", true)
Besides of controlling StateMachinePlayer
, it's useful to set arbitrary value with set_param
var smp = get_node("StateMachinePlayer")
smp.set_param("game", preload("game.scn"))
var game_scn = smp.get_param("game")
When playing scene, select
StateMachinePlayer
node in remote scene tree to view flow ofStateMachine
in realtime
Add
res://addons/imjp94.yafsm/src/debugger/StackPlayerDebugger.tscn
toStackPlayer
(so asStateMachinePlayer
) to visualize the stack on screen.
Check out gd-YAFSM-demo for how you can integrate gd-YAFSM into you project and manage app state with StateMachine
Refer to Documentation located in addons/imjp94.yafsm/README.md