• Godot Help
  • Does anyone know how to make a more "proper" state machine for a complex game?

I know how to make a basic state machine with code but, it can get messy if the game gets more complex. Now even though the code for the enemy's AI state machine is getting more complex; it's still managable. That said, the state machine could become hard to manage if I were to make the AI more complex; that's why I think it's important for me to know how to make a proper state machine as oppose to just relying on the Enum and match. I know it's possible to break up the code for a state machine across multiple scripts in a node hierarchy but, I just don't know how.
Can anybody help me? Does anyone know of any resource that would help?

cybereality I'm having a hard time understanding the pseudo-code examples but, I did learn a lot of helpful terms to look such as "state pattern" and it helped me to come across this video:

Yeah, that is C++ and kind of overly complex, but it's the official source of the pattern.

That video looks like a more practical example.

I wrote a pretty useful one for myself and it works pretty well and is not that difficult. What complexities are you experiencing and what features do you think you're looking for?

Mine is used like this to add states. Basically you add a function that you want to execute on that state with optional parameters as to what it does after the state is done:

                StateMachine.States.Clear();

                StateMachine.AddState(new KStateGeneric("growlevels")
                {
                    UpdateAction = (state) => { TimedFunction("Grow Levels", () => this.GrowLevels()); }
                });

                StateMachine.AddState(new KStateThread("growsectors")
                {
                    UpdateAction = (state) => { TimedFunction("Grow Sectors", () => this.GrowSectors()); }
                });

                StateMachine.AddState(new KStateThread(nameof(this.GenerateHeights))
                {
                    UpdateAction = (state) => { TimedFunction(nameof(this.GenerateHeights), () => this.GenerateHeights()); }
                });

(timedfunction is just a method that adds a stopwatch and prints the elapsed time so i can see how long things are taking)

In this example it just moves to the next state when one state is done. Thread states run on a thread and generic states run on the current thread, so background tasks don't have to get in the way. You then trigger a state like so:

StateMachine.SetState("first");

This triggers the state machine to start at the beginning, but you can trigger any specific state by name. I'm not sure what yours looks like or what issues you're having, but I think this is as simple of a setup as I can think of.

In this example I want my states to process in order and move to the next state when a state completes. If I wanted it to execute the state and stop then I would set the nextstate="none" when creating the state. You could also tell the state machine what you want it to do in the UpdateAction after it's done.

So basically you code your states to do what you want and set them up once, probably in _Ready(), then trigger them based on user input or game events. I will maybe eventually add trigger actions to this as well so it could automatically trigger states based on some pre-defined logic, but I don't need that yet so it's not there yet.

That looks amazing. I might have to use that. I was planning on GOAP for my game based on FEAR, but maybe they can be combined.