#Finite State Machine Implementations

31 messages · Page 1 of 1 (latest)

severe kindle
#

As an exercise I wrote out 3 broad categories of ways I can see someone handling a FSM.

  1. match statement
  2. dictionary or array
  3. polymorphism with states as objects

I am curious if there are other strategies not listed here, or which of these patterns people feel are generally better?

stray comet
#

I always will prefer ENUM vs String to check the status, because the String isn't checkable from the builder process, but the ENUM it is! 😉

Also for the "polymorphism" method, I'll prefer write a static base class with an empty method, and inherit a new static class for any new status (implementing the right method).

PS: using static classes, you haven't the need to create a new object to use a new status!

glad niche
#

If I did
enum {CONST1, CONST2, etc}
how/when do I assign values to them? or I don't?

stray comet
glad niche
#

Yeah I just did, thanks

stray comet
dawn bobcat
#

Good reference for me as well

stray comet
dawn bobcat
ember prism
# severe kindle As an exercise I wrote out 3 broad categories of ways I can see someone handling...

Very nice! Lately, I've been a fan of shaggydev's advanced state machine https://youtu.be/DPxIMVC0oZA?si=vu8hsPc3sK9eHHPw (source code link in the description -- its for Godot 3, but it's just a skeleton so it's easy to port). I've used variations of it for a few projects now. At first, it seemed unnecessarily complicated with all the inheritance and export variables, but I've found I actually spend way less time on both setup and debugging than simpler state machine implementations I've used.

Hierarchical state machines and dependency injection are two great techniques to know about when building your state machines in Godot. Let's look at how these techniques can be used to build upon the simpler implementation from the previous video on state machines and make something more flexible and reusable.

Intro: 00:00
Hierarchical state m...

▶ Play video
exotic sky
#

It depends on the complexity of the project. I think a good solution for an advanced state machine is something like this: https://gitlab.com/atnb/xsm

tight fossil
#

I've made one based on Resources recently. Has the charm of being expanded on without having to touch code.

stray comet
tight fossil
#

Basically, I create 3 Resources:

  • State
  • Condition
  • Transition

State is basically just a Resource with a text var that contains the name of the state. But of course you can expand on it, add variables with values for that state, for example.

Condition could be empty, as it's mainly the name of the resource itself that's interesting, but the way I've built it, I added a text var with a name, so I could push a condition to the state machine by name, not just by having a reference to the resource, so then I compare the condition text rather than the condition itself.

Transitions are a resource that combine the 2 above:

  • from: State
  • condition: Condition
  • to: State

The state machine itself has an export Array[State] and an export Array[Transition]. I can create my states, conditions and transitions either directly in the inspector or save them locally then drag them into the arrays. I then send either a Condition or a string to the state machine and it looks through its list to see if it has a matching pair of from and condition, then it executes the transition and emits signals based on that. I use 3 signals for that: StartState, RunState, EndState, so I can have a bit of setup and cleanup, when necessary.

I can show you the project if you like, once I'm back at my home pc.

glad niche
#

ok show me too ?

ember prism
stray comet
tight fossil
#

@stray comet @ember prism @glad niche

glad niche
#

how can I use this ?

tight fossil
#

I've added an example scene, have you looked into it?

glad niche
#

yes I did

#

I looked at the code

tight fossil
#

Well, the example scene uses the PlayerFSM.tres, a finite state machine that's created using the conditions, states and transitions created in the folder. The buttons push a condition to the FSM, the label listens to the change of the state and displays the state name.
You can use this kind of setup to communicate the states of a larger system between the components of that system.
How you use it eventually would be dependent on what kind of problem you're trying to solve.

severe kindle
#

Not to necro this post but I just realized this is probably an even easier method for handling state delegation if you want to stick to using a single script, rather than splitting it up into a bunch of different classes and stuff

#

All the array/dictionary stuff is pointless if you're just using callables anyways