How is a finite-state machine used?

Hello, I’ve just learned about finite-state machines when trying to look up something for my game I stumbled across this repo GitHub - unindented/lua-fsm: A simple finite-state machine implementation for Lua. and I wanted to get a better explanation on what exactly they’re used for as it seems like it could be helpful for what I wanna do, but I’m unsure if it’s actually going to be the correct purpose for it or if it’s even beneficial.

From my understanding so far you can make different states and then easily switch/transition between them and I guess having different things happen based on the current state? So for my game, I could potentially use it to have an idle state, jumping state, moving state, attacking state etc. And that’s really all I’ve gathered so hoping someone can give me a better understanding of them.

Also not sure if this is the correct spot for this, but last time I made a post similar to this someone told me to put it here so yeah.

Perhaps the wikipedia can help you grasp the usage?

From what I understand, a finite state machine is a bit of code that has different states and does different things in those states. For example, the following could be considered a finite state machine:

local State = 1

while true do
    if State == 1 then
        task.wait(0.5)
        State = 2
    elseif State == 2 then
        print("Something")
        State = 3
    elseif State == 3 then
        State = math.random(1, 2)
    end
    
    task.wait(1)
end

(Note: This is my understanding of FSMs, and I could be very wrong, but it’s what FSMs look like to me)

FSM is computer architecture 101. You’ll learn it in college and that’s about it. Don’t even worry about trying to use it in code it has no applications here and you’ll just confuse yourself more.

i tried looking around roblox for a state machine but ended up having to make my own. withholding mine because it’s very sloppy and complicated and i encourage you to make your own so that you can fully understand your system when you make it.

it’s been helpful towards making a character controller that can change your controls contextually like doing a higher jump if you’re pressing the jump button in the crouch state or ground-pounding if you’re pressing the crouch button in the jump state.

it’s also helpful for playing animations for certain states like having an idle animation play upon the transition to an idle state or having a rising jump animation play at the beginning of a jump state and a falling animation play once you transition to a falling state upon reaching the apex of your jump.

it’s helped out for multiple things and i’m glad i stumbled upon it. i recommend looking into it and figuring out how to make your own cuz it’s definitely helped in a lot of my projects

1 Like

Seems like you’re understanding it right.

Note that a “state”, as far as your FSM is concerned, can be as simple as one or more “settings” that define a thing. If we are talking about a door, we could say that it has two states: open and closed. For this simple example, we could define both states in code using the same variable, doorIsOpen = true or doorIsOpen = false.

The ‘finite’ part means that we have a limited number of these states. In the door example, it could technically be said that there are an infinite number of positions the door can take between open and closed. The FSM requires that we have something other than an infinite number of states. Due to the way FSMs are implemented, it’s generally true that the number of states you want will be equal to the fewest number of states you can get away with and still accomplish what you set out to do.

The ‘machine’ part is descriptive of the way that FSMs switch between these states based on inputs. That would involve the specifics of how we get from an open-door state to a closed one and vice versa—the mechanics.

So, yeah. In a sense, an FSM could be used for many situations where you can create a set of related states and define rules for how and when to transition between them. When implementing this in code, it’s convenient to use classes (OOP). Each state can be based on the same template, so the code that utilizes the states doesn’t have to care which state is active. For example, all the states may have methods like :enter(), :exit(), :update() and so on that have the same names but contain code that is relevant to the particular state. Within a method like the update, there may be code that just carries out the actions of the state. For example, if we’re now talking about a foraging state for an NPC, then the update will direct it to do, or continue to do, foraging things. That update code could also run checks that might indicate that the NPC needs to switch to a new state, and it could then initiate a state transition (rest or fight or whatever).

Since managing transitions is done in each state, each additional state you add increases the number of transitions you have to handle in your classes (since transitions could potentially be happening in all directions). That can become unwieldy and limits the usefulness of FSMs to situations with relatively few states. On the flip side, FSMs can be somewhat of a hassle to implement, which makes them unsuitable for simple situations. That small range of usefulness tends to make FSMs less common than one might expect.

FSMs sit between the simpler solutions like if-elseif conditionals and decision trees and more complex options like behavior trees, that might scale better.

7 Likes