4.4
Hi, i’ve noticed people use state machines for players, enemies, floors, bosses, for their games, why? Can’t you just code the stuff without needing to make states?
Well yeah, i get it, state machines are cleaner i guess, but are they needed ?
4.4
Hi, i’ve noticed people use state machines for players, enemies, floors, bosses, for their games, why? Can’t you just code the stuff without needing to make states?
Well yeah, i get it, state machines are cleaner i guess, but are they needed ?
Yes, of course you can do without a state machine.
A state machine is a tool used to solve a specific problem. If you do not have that problem then you do not need the tool.
You may, however, notice that you are coding what looks an awful lot like a state machine by default.
I think it would only be a mistake if you deliberately tried to avoid using a state machine even though you did run into a problem easily solved by states.
no you can’t.
there is no other way to code a player. a player with animations, has states. each animation needs a state, is a state. even if there are no animations there are still states, like death or alive, can move or can’t move, shooting or reloading.
even if it shoots, there’s a state where it can shoot and one where it can’t, which is the delay between shots.
there are many kinds of state machines, but you need one and in some cases more than one to make the game work at all.
the mistake many make is trying to code without first thinking of all the things the player must be able to do, and then they end up with code that doesn’t work. the advantage of a state machine is that more states can be added later.
do you have any tutorial or document for this, it’s always confusing to me.
Hi, late here… So do i remove all my code and change it into a State Machine?
Feel free to not answer!
Thanks.
A state machine is one of many design patterns that can be useful in some scenarios, but not in others.
I highly recommend a book written by Robert Nystrom called “Game Programming Patterns”, the entire book is available for free online on the author’s own website:
https://gameprogrammingpatterns.com/
And in your case, I would highly recommend giving the State chapter a read, or just a quick glance!
He does his best to explain what a state machine is, what it does, and why it’s NOT a good fit for a lot of scenarios.
https://gameprogrammingpatterns.com/state.html
All in all, using Design Patterns is absolutely not a requirement as someone pointed out before, but once you made a game / finished your first project, it’s definitely a good path to go down on, to learn more and see what can be improved. Design patterns don’t necessarily seem very useful at first, but as your game grows, you’ll appreciate them more and more. The more complex your code gets, the harder it is to add new features to it or modify already existing ones, and that’s where design patterns will help you in big ways. But as an absolute beginner, you should focus on learning the basics first, then moving onto slightly more advanced topics!
But most importantly, have fun doing it!
Thanks! I’m learning alot from this community!
Here are my two cents on this: no, state machines are not needed.
However, by the nature of writing a game - you are inevitably gonna have some states (variables, objects, resources etc) and code that reacts to that state or mutates it (game over screen, function that heals player etc)
Whether or not you implement that as an official “State Machine” pattern - is fundamentally irrelevant to the player. Writing it one way rather than the other is just trading pros and cons from those two specific implementation approaches. In Godot you can implement state machine as simple combination of enum and ifs, or you can make your own custom nodes that track transitions and such.
The best way to know which approach, what implementation to use and when - is through experience. As you learn more, you will encounter more problems and in the future you will be more informed when coming across similar problems. Sometimes few if statements are enough for “state machine” for a jam game if you know you will not need more, sometimes on the larger scale projects implementation of state machine may be different based on whether you are making a roguelike or visual novel.
My best advice would be not to overthink it and just start coding, but keep an open mind when it comes to thinking about the code as you are writing it. Do you sense friction when adding features? Do you feel overwhelmed by what you need to do to change something in the code? After that, write a note (either mentally or physically) to yourself in future about what you can do differently in the future to avoid that bad experience. This is usually what engineering journals are for. The reason I think this is vastly superior to whatever some other book says is that it is written in your own language and tailored towards your way of thinking, based on your own experience. Not saying that reading books does not help - but ultimately it is inferior to trying things out by yourself and learning from the experience.
hi, well I don’t know what your code looks like. a simple game where you just move left and right and jump could get away with some simple code and booleans
. but if you need to add more mechanics like swimming, attacking, powerups, even cinematics, you do need a state machine of some kind.
you also do need one if using animations, because animations use states. a game with animations can’t be made without a state machine of some kind.
the simplest and most powerful way is to use an AnimationTree
, which requires an AnimationPlayer
, which works with Sprite2D
.
this requires minimum code, it’s easy to setup and very powerful.
I see a lot of people following tutorials that use AnimatedSprite2D
, and those DEFINITELY DO need a state machine, because there is no other way to keep track of the animations. and in the end, newbie programmers following a tutorial end up with messy code that breaks, and I’ve seen at least 4 such issues opened in this forum in the last week alone, because they play an animation in the idle and then call a signal and play the attack or die animation and it doesn’t work because they are already calling the other animation and it overrides it.
you don’t need to scrap everything, code can be easily moved and improved, and this is something that needs to be done constantly anyways.
a very simple state machine for a character would look like this:
const SPEED : float = 10.0
const JSPEED : float = 4.0
enum {NORMAL, ATTACKING, JUMPING}
var state : int = 0
func _physics_process() -> void:
var input_dir : Vector2 = Input.get_vector("left", "right", "up", "down")
match state:
NORMAL:
if is_on_floor():
#play idle anim
velocity.x = input_dir.x * SPEED
if Input.is_action_pressed("jump"):
velocity.y = -400.0
state = JUMPING
#play jump anim
if Input.is_action_pressed("attack"):
state = ATTACKING
#play attack anim
else:
#play falling anim
velocity.y += gravity * delta
JUMPING:
velocity.x = input_dir.x * JSPEED#move slower
if is_on_floor():
state = NORMAL
else:
velocity.y -= gravity * delta
move_and_slide()
you can just move your code inside a state and start removing booleans, which will lead to cleaner code, which will mean fewer bugs, and allow you to do more.
you can still combine other patterns into it, like using animation_finished signal, but instead of playing an animation, you have to change the state.
How do i use enums? My code is the msessiest of the messiest, its disorganized, i even forgot what most of my code does too, so how can i use enum as a state machine if i dont even remember what my code does? Do i rewrute my code?
Enums are ultimately a way to track one of many values, under the hood enums are stored as integers. The benefit of using enums is for code organization and safety; organization because enums make this much more legible
if state == 0: # what does zero mean?
position.x += 100 * delta
elif state == 1: # and 1?
position.y -= 80 * delta
# versus with enums:
enum States {MOVE_RIGHT, FLOAT_UP}
if state == States.MOVE_RIGHT:
position.x += 100 * delta
elif state == States.FLOAT_UP:
position.y -= 80 * delta
In the second example you cannot accidentally use a invalid value, such as 2
or 3
, which wouldn’t trigger an error in the first example, you’d be left wondering why your enemy doesn’t move for no reason. If you used strings for your states such as state == "move_right"
, then the same silent error could happen with state == "move_r1ght"
, and you’d have no help debugging. Thus enums can aid in code safety, along with autocomplete.
As other have suggested, dive deep into why your code is hard to work with, what parts you are finding hard to remember; write it down and take it apart, see how you can improve your code. Maybe StateMachines will help, maybe not, it depends on what you are trying to make.
State machines are super interesting – in other fields of coding, they’re kind of irrelevant thought experiments that don’t matter much. But in game development, they’re absolutely necessary for almost everything. Well, okay, you could do without, but it would definitely not look as pretty, nor be as readable/digestible.
I had a friend in a different sector of the tech industry shocked that I work with state machines so much. “Aren’t those just college assignments?” Well, not in game development, and that’s the case whether we’re talking Godot, Unity, Unreal, etc.
I am not certain I agree with this. I dealt with states constantly but we never really thought of them as ‘state machines’. The difference I think is that in games the state machines are much more tangible and noticeable.
For an example lets take a simple form on a website. The states you are dealing with are form submitted, form errors, missing fields, etc. Your ‘state machine’ or form processor has to deal with all these states.
Take a simple user processing online, is the user logged in, are they authenticated, are they authorised for such and such, are they on the free service or the paid service, have they paid, are they within account limits etc etc. Your user system ‘state machine’ has to deal with all these states.
Or just take fetching data from a database, sending response, awaiting response, valid response recieved, invalid response recieved, timed out response, etc etc. Your db backend and frontend have to deal with all these states.
These are all states and state machines are used to deal with switching from one state to another. In fact it is pretty hard to think of an example that does not have associated states. Even a simple menu, clicked, hovered, previously clicked, has submenu, submenu open, submenu collapsed etc etc etc. All states and even your css would have to deal with those states.
It makes me wonder what sort of coding your friend is doing where they think dealing with states and therfore using ‘state machines’ to deal with them are not common place. Even HTTP requests have states, although you may not be exposed to the state machine running them necessarily, you most certainly have to deal with them.
Anyway, just thought about this after reading your post, so thought I would share the thought.
PS Just thought of another one too. An ecommerce basket process is pretty much a state machine all by itself. And dealing with checkout and bank payment systems is another one entirely.
State machines are a very simple concept and powerfull as hell.
I think you have a good point with regards to it not being obviously a state machine – I think most programmers work with state machines without even realizing it. I suppose a proper rewording would be “most programmers don’t make their own state machines, but in game dev we do constantly”? Since a lot of those state machines, especially with web dev stuff, are already provided by the backend/API, so many devs aren’t writing state machines.
That said most people I know in programming that aren’t game dev are low level C/C++ programmers, not web development. But I haven’t talked to all of them about state machines, I’d be interested to see if they write any themselves or not.
Great point! Writing my own state machine has honestly been a real eye-opener. I think I must have rewritten it at least ten times before settling on a format I’m actually proud of. And, to be honest, I’m sure it’ll keep evolving as I learn more.
Regarding the original question:
Can’t you just code the stuff without needing to make states?
Well yeah, I get it, state machines are cleaner I guess, but are they needed?
In my experience, the answer is a definite yes, they are needed - especially if you want to avoid your code turning into spaghetti. My current setup actually separates concerns even further: I have a state machine, but I also introduced what I now call a “behaviour machine.” The key difference is that my states no longer decide what comes next; instead, the behaviour machine acts as the brains behind enemy actions, determining which state should be active. The state machine has become more of a supporting player, purely dealing with a single state, while the behaviour machine handles the real decision-making.
Building a behaviour machine turned out to be much more challenging (and interesting!) than the state machine. While the state machine is all about “in this state, do this,” the behaviour machine asks, “If this is happening, and it happened here, and something else happened before, then do that.” It has to interact with all the game logic and directs the state machine, making it a much more dynamic and complex system.
I’ll admit, before this project, I’d never consciously built a state machine, and it was a fun learning experience. But compared to designing the behaviour machine, the state machine now feels almost straightforward.
Not sure what a senior Godot developer would make of my code, but I’m genuinely proud of how far it’s come at least IMHO.
Hi! That reminds me of a youtuber called InBoundShovel! I think he does something like that? Super cool! But it’s preeetty difficult to do a behavior machine right? I mean.. As a beginner i don’t think i can make a behavior machine because sounds confusing to code
Not really but this is my first. I wanted a way to create different behaviours for my enemies as simply as possible. I was finding it a bit spaghetti like where states were being changed and called etc. Here is a simple example:
An enemy ship detects my player, so a signal is sent to the behaviour manager to say “handle_enemy_detected”.
The behaviour manager has to check several things before choosing a state. Is the enemy stunned or not? Is the enemy in an attacking stance? Is there enough ammo? Does it need to alert its allies? Is it guarding something else? Only then will it tell the state manager to run away, or position itself in a defensive structure, or attack fully, or alert nearby allies, or retreat to a nearby military force.
Now all that stuff is in one place, a single file, and the behaviour manager is called from all over the place. But wherever it is called from, any change in enemy behaviour is decided in this one file. And to alter the behaviour, I can just adjust this one file. Previously states were being called from the engines, from the sensors, from the collision manager, from other entities too, and the different states had to do all the checking of all the factors. Now they do none of that. They simply deal with their state.
Another good example is when an enemy is attacking and their target is lost, what do they do. Well they simply tell the behaviour manager. The behaviour manager asks should we be searching the area now, or patrolling, or returning to our orbit, or meandering or swarming with our allies etc. Lets say it decides it should be patrolling, the state manager is told to change state to patrolling. (It exits the attacking state, enters the patrolling state and that then takes over as normal). But if I want to change the behaviour, I only have to do it in one place.
I am still exploring the power of this approach but anyway, I feel like I type too much sometimes. Sorry. It is just so exciting and there are not enough hours in the day!!!