How to implement / create a state machine?

I was working on a combat system and thought it seemed a bit messy. While I was looking some things up, I found out about state machines. After researching them a bit, I mostly understand the gist of state machines and I’d like to try using one. Problem is, I’m really lost on actually implementing one into my game. How would I go about doing something like this?

(I’m not asking you to exactly create me a state machine, but guide me on how it could be done and what the process may be like to help me further understand how to create one myself)

Here’s a flowchart for a combat system I’m working on


Do I have the right idea of using a state machine to achieve something like this or am I better off with a different method? I’m mostly just trying to make my code more polished and neatly written and I believe this could help me accomplish that

11 Likes

My game’s combat system uses something similar to this. I use different Values, like Number or String Values, to store information about each enemy. E.g., it’s bounty, if it’s idle or attacking, what attack it’s using, etc.

Something you could do is for each state, have a list of transitions. These transitions are what dictate if you can go to another state. Transitions should be based on some sort of condition to go to the next state. If you need a code example I would be happy to give some because I use this sort of system for animations.

1 Like

A code example would be wonderful!
Looking up things about state machines, I get what they’re doing but I can’t wrap my head around how they’d work. In this scenario, I have it so that you can’t dodge without blocking… would each state just be a string or variable? I read something about state machines where it first spoke about how state machines solve the issue of having a variable for if you’re in this state, can you do this, can you not do this, and hardcoding a bunch of things in. I don’t know how I’d do something like this without hardcoding in what you can and can’t do within each and every state. I guess this is the biggest issue I’m having which I should have further specified. Could you also elaborate on the transitions? Sorry if I’m asking too much lol

Sorry to butt in, but you could do something like this:

local States = script.Parent.Info.States
local CanBlock = false
local Attacking = States.Attacking.Value
local Blocking = States.Blocking.Value
local Guarding = States.Guarding.Value
local Stunned = States.Stunned.Value
local Idle = States.Idle.Value
local HasBlocked = false
local Parried = States.Parried.Value
local ParriedBy = States.Parried.ParriedBy.Value

if Blocking = true then HasBlocked = true
if HasBlocked == true then CanDodge = true

local function TryDodge(Health)
if Health < 50 and Idle == false and HasBlocked == true then
-- Do your animations and stuff
end

local function TryAttack(Health,Parried,ParriedBy,Target)
if Parried == false and Attacking == true then
-- Play Animation
if Parried == false and ParriedBy ~= nil then -- Check if attack was parried while animation was playing.

Target.Health = Target.Health - 10
end
end


Example Hierarchy:
image

This is missing a lot of things and doesn’t define targets or attacks, but hopefully, it works as an example.

To directly answer your main concern, you can just run a check every time you try to do an action that makes sure you’re in the right state and things are correct.

2 Likes

My finite state machine system is very much tailored towards animation so this may not be the best approach for what you want. This may however provide some insight.

Assuming you are familiar with OOP, I have a class called FSM (Finite State Machine) that handles the states and transitions.

local Machine = FSM.new({
	Paramaters = {
		["Is Jumping"] = FSM.ParamaterType.Boolean;
	};
	
	States = {
		["Idle"] = {
			Transitions = {
				{
					TargetState = "Jump";
					Conditions = {
						Paramater = "Is Jumping";
						Target = true;
					};	
				};
			}
		};
		
		["Jumping"] = {
			Transitions = {
				{
					TargetState = "Idle";
					Conditions = {
						Paramater = "Is Jumping";
						Target = false;	
					}
				};	
			}	
		};
	};
	
	Entry = "Idle";
})

This is not exactly how my code is setup, I simplified it quite a bit. What this shows is that each state has a list of transitions to other states. These transitions are fired when it’s conditions are met. For example the Idle state goes to the Jumping state when the Is Jumping parameter is set to true.

The way this happens is like so:

Machine:SetBoolean("Is Jumping", true)

This doesn’t take into account the code that actually needs to be run when you enter a new state, but it’s relatively simple. Like I said, this is probably not the best solution for what you want because it is mostly meant for animation, but it might give you an idea of the basic concept at hand.

4 Likes

It’s alright, though I don’t believe this is quite what I’m looking for, plus it seems to suffer from the same issue I’m trying to solve (lots of hardcoding what can and can’t be done)

1 Like

TBH: You don’t need a FSM or OOP really to complete a decent combat system on Roblox.

Some Ideas Though:

  1. Use OOP and some CombatState parent class then override telemetry-dependent methods depending on the active state. Assign the new user combat state based on the current active combat state data member as well as the user input (i.e. Press R, Release R, Clicking, etc).

  2. Create some sort of adjacency matrix dictionary between combat states and user inputs. For example, when the combat state “Idle” is true, and Clicking occurs, the active state switches to Attacking. This would effectively create a pseudo-network of nodes and edges in a Lua dictionary. It would still require fair amounts of hardcoding.

*Sidenote: My responses are rough ideas, not really concrete examples.

2 Likes

Thank you, this actually helps quite a bit with my understanding of how to go about making a state machine!

I agree with you on this, and I feel like a state machine could be a bit too much for something like combat. I’m just trying to find ways to make my code more neat, polished, and efficient.

I’m still pretty new to OOP, though trying to learn, so I’m slightly confused by

I’m also a little confused by

and

Would you mind providing further insight into these?

Good point to jump in since I was shown a FSM created in Lua on GitHub. You probably could’ve searched for this too. It does work in Roblox as well.

9 Likes

Most of what I said was just conceptualizing the problem. To be honest, I wrote you like an 80 line module w/ a constructor, valid states, a table of functions, etc., but I think that would just confuse you.

To simplify this, perhaps create a table of string states, and use ContextActionService (CAS) to bind those strings to functions that do things you want your combat system to do. The CAS has bind and unbind functions that link telemetric input like keyboard button presses with desired functions. To make a combat system with CAS, simply temporarily bind a state like “Idle” with an input like MouseClick and then bind it with a function that activates attacking functions. Once you are state “Attacking” call CAS’s unbind for “Idle” and bind “Attacking” appropriately for that state. So in basic terms, for every node on the picture you posted in the original post, have a state, for each state, use CAS to bind and unbind depending on inputs.

I think this would be much easier than modularizing or OOP-ing this into something like a FSM.

2 Likes

That’s actually a pretty cool idea, I’ll try it out. Just out of curiosity, could I see the module? I may not understand it but I usually find it easier to read and see what the code is doing than to read about it. Thanks for the help!