2023-02-14 16:53:42 +01:00
2023-02-14 16:07:11 +01:00
2023-02-14 16:53:42 +01:00
2023-02-14 16:07:11 +01:00
2023-02-14 16:53:42 +01:00
2023-02-14 16:07:11 +01:00

Description

I wanted to just use a state machine purely in GDscript, as simply as possible, but with states, transitions, hooks, and conditions/triggers to change states

  • States: the FSM will always be in a state. It will change to another state with the transitions, following the first transaction, having the current state as a source, that matches the conditions/trigger
  • Transition: a transition will allow the FSM to change from one state to another when, at each update
    • The transition is fully matched the (optional) trigger has been called
    • The (optional) conditions has all been met
    • A transition is composed of
      • A state source
      • A state destination
      • An optional list of conditions
      • An optional trigger
  • Transition source: in order to reduce the amount of code to type for transitions, there are some helpers. source can be a string (STATE), or it can be an array:
    • STATE: any known state (the easy one)
    • "*": all the states (including the destination)
    • ^STATE: all the states but STATE. e.g. "^hurt" => it will match, for source, all the states except "hurt"
    • -STATE: remove STATE from the previous states added (when source is an array). e.g. ["*", "-idle", "-hurt"] => it will match, for source, all the states except "idle" and "hurt"
  • Trigger: a transition can be mapped to 0 or 1 trigger. A trigger is emitted by calling the "trigger" method, and the trigger will be treated at the next update and then forgotten
  • Condition: a condition is just the callback of a method returning a boolean. It can be the name of the method, or it can prefixed by "!" to get the reverse boolean

TODO

  • Maybe optimize the whole thing

How to use

    mkdir -p addons
    cd addons
    git submodule add ssh://git@git.abxy.fr:212/groug/godot_simple_state_machine.git
  • Add the custom StateMachine node (name it "StateMachine" for the purpose of the example)
  • Initialize the states, initial state and conditions:
	$StateMachine.add_state("idle")
	$StateMachine.add_state("hurt")
	$StateMachine.add_state("dead")
	$StateMachine.set_init_state("idle")
	$StateMachine.add_transition("idle", "hurt", [], "fire")
	$StateMachine.add_transition("hurt", "dead", ["has_stuff_been_handled", "is_dead"])
	$StateMachine.add_transition("hurt", "idle", ["has_stuff_been_handled"])
  • Trigger an event
	$StateMachine.trigger("fire")
  • Add a condition: it's just a func returning a bool
    def has_stuff_been_handled():
        return true
  • Add callbacks for state entering/update/exiting: just add the state name in on_XXXXX_state_YYYY()
    func on_idle_state_enter():
        pass

    func on_idle_state_update(delta):
        pass

    func on_idle_state_exit():
        pass
  • Enabling debug mode (logs when changing states)
    $StateMachine.set_debug_enabled(true)
  • Get the current state
    $StateMachine.get_current_state()
  • Get the last known state (before the current one)
    $StateMachine.get_last_state()

Credits

icon: made by Freepik from https://www.flaticon.com, license: Creative Commons BY 3.0

Description
Godot pure-script FSM addon
Readme 210 KiB
Languages
GDScript 100%