Reference List for Creating State Machines in Unity with Focus on Character Controllers

September 23, 2020

State Machines

Unity and Character Controller Focus


Title: The State Pattern (C# and Unity) – Finite State Machine
By: One Wheel Studio
Youtube – Tutorial #1


Title: How to Code a Simple State Machine (Unity Tutorial)
By: Infallible Code
Youtube – Tutorial #2


Title: Complex Enemy Behavior using Finite State Machines – 2D Platformer – Part 13 [unity]
By: Bardent
Youtube – Tutorial #3


Title: State Machine Setup – 2D Platformer Player Controller – Part 21
By: Bardent
Youtube – Tutorial #4


Title: Movement State Machine – Free download
By: Epitome
Youtube – Tutorial #5


Title: Unite 2015 – Applied Mecanim : Character Animation and Combat State Machines
By: Unity – Aaron Horne
Youtube – Tutorial #6


Overview

I have dealt with using state machines before, but mostly for creating AI systems. I wanted to investigate using a state machine specifically for a player controller, focused on 2D player controllers if possible. With this in mind, I just gathered many resources on more general state machine concepts and design with a mix of more player controller focused examples when possible.

The quick breakdown is as follows:

  1. Tutorial #1 – General Finite State Machines
  2. Tutorial #2 – General Finite State Machines
  3. Tutorial #3 – AI Finite State Machines
  4. Tutorial #4 – Player Controller Finite State Machines
  5. Tutorial #5 – Player Controller Finite State Machines
  6. Tutorial #6 – Player Controller/General Finite State Machines

Tutorial #1

This is a great quick tutorial on Finite State Machines and implementing them in general in C# and Unity. It covers the various levels of state machine implementations and the pros/cons of each tier of state machine organization. This is a fantastic starting point for state machines.

Tutorial #2

This tutorial is a more general state machine but it does still have a focus on turn based gameplay. While I was focused on player controller FSMs, I am also interested in how to use these for game states in turn based play so I wanted to record this.

Tutorial #3

This tutorial focuses more on AI FSMs, which I have more experience with, but I still wanted to grab a reference to this as a decent looking tutorial on implementing an FSM in general. I also have another Bardent tutorial that is a player controller focused FSM so I thought this also might help me tie in my prior experience if I followed this approach.

Tutorial #4

As mentioned above, I have two tutorials from the same tutorial set and this is the second. I am hoping there is an overlap in the two systems that I can also take away from by observing what they are able to recycle between them. I also hope this will help make this FSM make more sense since I can tie in my prior AI FSM experience.

Tutorial #5

This is a quick tutorial that directly shows the setup for a player controller FSM. It appears that it might not be the ideal architecture I am looking for, but it could still serve as a good example when starting to design a player controller FSM.

Tutorial #6

This older (from 2015) Unite talk goes a bit more in depth into the combination of character animation and combat state machines. This could be a strong next step for me to look into after focusing on movement for the core of the player controller state machine. I am especially interested in seeing if I can implement their combat combos with their FSM approach in some capacity, as well as if they have an input buffering design I can learn from.

UnityLearn – AI For Beginners – Finite State Machines – Pt.02 – Finite State Machine Challenge

April 6, 2020

AI For Beginners

Finite State Machines

Finite State Machines


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

Finite State Machine Challenge

This tutorial provided a challenge to complete and then provided a solution. The challenge was to create a state where the npc would retreat to an object tagged as “Safe” when the player approached the NPC closely from behind.

My Approach

Since they had a State enum named Sleep already that we had not worked with yet, I used that as the name of this new state (I started with Retreat, but then found the extra Sleep enum so I changed to that since I assumed it would be more consistent with the tutorial). Similar to the CanSeePlayer bool method added to the base State class for detecting when the player is in front of the NPC, I added an IsFlanked bool method here that worked similarly, but just detected if the player was very close behind instead of in front. I used this check in the Patrol and Idle state Update methods to determine if the agent should be sent into the new Sleep state.

In the Sleep state itself I used similar logic from the Pursue state for the constructor, so I set the speed to a higher value and isStopped to false so the NPC would start quickly moving to the safe location. In the Enter stage I found the GameObject with tag “Safe” (since this was set in the conditions for the challenge to begin with) and used SetDestination with that object’s transform.position.

The Update stage simply checked if the npc got close to the safe object with a continuous magnitude vector check, and once it got close enough, it would set the nextState to Idle before exiting (since Idle quickly goes back to Patrol in this tutorial anyway, this is the only option really needed).

Finally, the Exit stage just performs ResetTrigger for isRunning to reset the animator and moves on to the next State (which is only Idle as an option at this time).

Their Approach:

Most of what they did was very similar, although they did make a new State named RunAway instead of the extra Sleep State, so I could have stuck with Retreat and been fine.

Notable differences were that they checked if the player was behind them by changing the order of subtraction when performing the direction check (changed player – npc to npc – player) where I just had the angle check use the negative forward vector of the npc instead of the positive vector. These give effectively the same results, but I liked my approach better since it matched up with what was actually being checked better.

They also set the safe gameObject immediately in the constructor, where I was setting this in the Enter stage of the State. Again, this basically gives the same results in most cases, but I think their approach was better here just because the sooner you perform and set that FindGameObjectWithTag the better I think just to make sure it has access when it does need it.

Finally, for their distance check to see if they had arrived at the safe zone, they used a native NavMeshAgent value, remainingDistance. I used the standard distance check of subtracting the vectors and checking the magnitude, so these again both give similar results. Mine is more explicit in how it is checking, and the NavMeshAgent value is just cleaner, so these both had pros and cons.

Summary

This was a nice challenge just to work with a simple existing finite state machine. Similar to what they mentioned in the tutorial, I think setting the safe object in the static GameEnvironment script and just pulling from that (instead of using FindGameObjectWithTag every time the NPC enters the Sleep/RunAway State) would be much more efficient. Also just to help with checking states and debugging, I added a Debug.Log for the base State Enter stage method that just returned the name of the current State as soon as it was entered each time. This let me know which State was entered immediately when it was entered, so this also helped show me when the states were entered, so this was a very nice state machine check that only required a single line of code.

UnityLearn – AI For Beginners – Finite State Machines – Pt.01 – Finite State Machines

April 1, 2020

AI For Beginners

Finite State Machines

Finite State Machines


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

Finite State Machines

Finite State Machine (FSM): conceptual machine that can be in exactly one of any number of states at any given time.
Represented by a graph where nodes are the states, and the paths between them are the transitions from one state to another. An NPC will stay in one state until a condition is met which changes it to another state.

Each state has 3 core methods: Enter, Update, Exit

  • Enter: runs as soon as the state is transitioned to
  • Update: is the continuous logic run while in this state
  • Exit: run at the moment before the NPC moves on to the next state

State Machine Template Code (Can use core of this for each individual state):

public class State
{
public enum STATE
{
IDLE, PATROL, PURSUE, ATTACK, SLEEP
};

public enum EVENT
{
ENTER, UPDATE, EXIT
};

public STATE name;
protected EVENT stage;

public STATE()
{ stage = EVENT.ENTER; }

public virtual void Enter() { stage = EVENT.UPDATE; }
public virtual void Update() { stage = EVENT.UPDATE; }
public virtual void Exit() { stage = EVENT.EXIT; }

public State Process()
{
if (stage == EVENT.ENTER) Enter();
if (stage == EVENT.UPDATE) Update();
if (stage == EVENT.EXIT)
{
Exit();
return nextState;
}
return this;
}
}

Creating and Using A State Class

State class template (similar but slightly different from last tutorial, with some comments):

public class State
{
public enum STATE
{
IDLE, PATROL, PURSUE, ATTACK, SLEEP
};

public enum EVENT
{
ENTER, UPDATE, EXIT
};

// Core state identifiers
public STATE name;
protected EVENT stage;

// Data to set for each NPC
protected GameObject npc;
protected Animator anim;
protected Transform player;
protected State nextState;
protected NavMeshAgent agent;

// Parameters for NPC utilizing states
float visionDistance = 10.0f;
float visionAngle = 30.0f;
float shootDistance = 7.0f;

public State(GameObject _npc, NavMeshAgent _agent, Animator _anim, Transform _player)
{
npc = _npc;
agent = _agent;
anim = _anim;
stage = EVENT.ENTER;
player = _player;
}

public virtual void Enter() { stage = EVENT.UPDATE; }
public virtual void Update() { stage = EVENT.UPDATE; }
public virtual void Exit() { stage = EVENT.EXIT; }

public State Process()
{
if (stage == EVENT.ENTER)
Enter();
if (stage == EVENT.UPDATE)
Update();
if(stage == EVENT.EXIT)
{
Exit();
return nextState;
}
return this;
}
}

Notice that the public virtual methods for the various stages of a state look a bit awkward. Both Enter and Update set the stage to EVENT.UPDATE because you want them to be setting stage equal to the next process called, and both of them would look to move that to Update. After entering, you move to Update, and each Update wants to move to Update again until it is told to do something else to Exit.

They also started to make actual State scripts, which create new classes that inherit from this base State class. The first example was an Idle state with little going on to get a base understanding. Each of the stage methods (Enter, Update, Exit) used the base versions of the methods from the base class as well as their own unique logic particular to that state. Adding the base methods within just ensured the next stage is set properly and uniformly.

Patrolling the Perimeter

This tutorial adds the next State for the State Machine, Patrol. This gets the NPC moving around the waypoints designated in the scene using a NavMesh.

They then create the AI class, which is the foundational logic for the NPC that will actually be utilizing the states. This is a fairly simple script in that the Update simply runs the line:

currentState = currentState.Process();

This handles properly setting the next State with each Update, as well as deciding which state to use and which stage of that state to run.

It turns out running the base Update method at the end of all the individual State classes’ Update methods was overwriting their ability to set the stage to Exit, so they could never leave the Update stage. They fixed this by simply removing those base method calls.

Summary

Using Finite State Machines is a clean and organized way to give NPCs various types of behaviors. It keeps the code clean by organizing each state of behaviors into its own class and using a central manager AI for each NPC to move between the states. This also helps ensure an NPC is only in a single state at any given time, to reduce errors and debugging.

This setup is similar to other Finite State Machine implementations I have run into in Unity. The Enter, Update, and Exit methods are core in any basic implementation.

UnityLearn – Beginner Programming – Finite State Machine – Pt. 02 – Finite State Machines

Novemeber 18, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Finite State Machines

Building the Machine

This part of the tutorial has a lot more hands on parts, so I skip some of the sections for note purposes when there is not much substance to them other than following inputs.

A key in finite state machines is that an object can only ever be in exactly one state at a time. This helps ensure each state be completely self contained.

Elements of a Finite State Machine:
Context: maintains an instance of a concrete state as the current state
Abstract State: defines an interface which encapsulates behaviors common to all concrete states
Concrete State: implements behaviors specific to a particular state of context

To get started in the tutorial, they created a public abstract class PlayerBaseState which will be the abstract state for this example. PlayerController_FSM is the context. They note that while in this case all the abstract state methods take the PlayerController_FSM (the context) in as a parameter in this case, that does not necessarily have to be the case for the general FSM pattern.

Concrete States

It is noted that the context in a FSM needs to hold a reference to a concrete state as the current state. This is done in the example by creating a variable which holds that of the type that is our abstract state, which is PlayerBaseState in this case. They then create a method called TransitionToState which takes a PlayerBaseState in as a parameter. It then sets the currentState to that parameter state, and then calls the new state’s EnterState method (all states have this method as it is dictated by the abstract class they all implement). This determines what actions should be done immediately upon entering this new state.

Example:

public void TransitionToState(PlayerBaseState state)
{
currentState = state;
currentState.EnterState(this);
}

The tutorial also shows a way to take control of the context’s general Unity methods and pass the work on to the concrete states instead. This example did this with Update and OnCollisionEnter. The abstract state, and in turn, all of the concrete states, have their own Update and OnCollisionEnter method. The context, PlayerController_FSM, then simply calls currentState.Update(this) in its Update method, and currentState.OnCollisionEnter(this) in its OnCollisionEnter method, so that the current concrete state’s logic for these methods are used without flooding the context itself with any more code.

Since it is necessary that your context has some initial state, they do this by simply calling the TransitionToState method within the Start method and entering the IdleState. IdleState is the initial state for this case.

Beginning the Implementation

Important benefits seen using this system:
While working on the concrete classes themselves, we never needed to go back to the PlayerController_FSM class (the context) to modify any code there. The entire behvior is handled within the concrete states and is abstracted from the character controller (the context). Setting expressions was much easier as no checks are needed and this can just be set in the EnterState method of each concrete state.

It is already clear that this method removes a lot of boolean checks from the overall code, and helps organize the code by ensuring any logic about a state is contained within the class for that state itself (with less bleeding into the code of other states).

Continuing the Implementation

It is worth noting that PlayerController_FSM holds a reference to every concrete state except the spinning state. This was done because they actually have the jumping state create a new spinning state on transition each time it is invoked. They apparently do this so that the local field for rotation within the spinning state is reset to 0 each time it is called, but it seems like there would be other ways to do this that seem less wasteful (such as resetting it to 0 when exiting the state). I am also not sure if this is intended behavior, but the spin also immediately cancels upon contacting the ground (resetting the player rotation to 0) with this setup, where as in the previous behavioral setup the spin completed even if the player contacted the ground.

Module Conclusion

Benefits of FSM:

  • More modular
  • Easier to read and maintain
  • Less difficult to debug
  • More extensible

Cons of FSM:

  • Take time to setup initially
  • More moving parts
  • Potentially less performant

Just something very notable with this approach, it seems much harder for me to break than the naive implementation. If I spammed key presses (like pressing jump and duck a lot) with the naive approach, sometimes I could break the system and have the player stuck in the duck position or be ducking while jumping. I have not been able to break it at all with the full FSM setup, which makes sense since transition behaviors solely exist within the states themselves so these inputs cannot be jumbled in any way.

SUMMARY

Using state machine systems appear way easier to use and build on than the “naive” approach of basic boolean behaviors (with lots of if statements and boolean checks). Not only was I very excited about how much easier this appears to work as a scalable option, it also just worked better and more cleanly when it was all put together.

The other version had small bugs that would pop up if you spammed all the different action keys (such as getting stuck ducking or being ducked in a jump), which were possible just because the key presses would get recorded before reaching the bools or if statements that should be telling them that they are not proper options. These very separated states make that type of error impossible as it is only concerned with a single state at a time.

This type of system just seems much cleaner, more organized, and less error prone than what I have done before and I am very excited to try and build a system like this for my own project (for both players and enemy AI).

AI State Machine Tutorials: Tutorial #2

September 25, 2019

Tutorial #2

From Blog Post: Unity Basic AI State Machine Tutorials

Youtube – Unity 3D – Make a Basic AI State Machine

Tutorial #2

By: Joey The Lantern


General Structure

There is a general state machine class, a class for each individual state, and then the class for whatever will be using these states. This format is very similar to the first AI state machine tutorial I followed by UnityCollege3D.

State Machine

They created a new namespace, StateStuff. This was because they did not want anything to be a monobehaviour. This namespace then holds the StateMachine class as well as a public abstract class State. They mention that could be used in place of to allow you to specify what types can use this class, but they went with because it’s more ambiguous and works with more things. This is something I will need to look into, but I am guessing at this point T just means any type. So basically anything can use the StateMachine.

The state machine class was given two variables, State currentState and T Owner. These are both set in a constructor for StateMachine. Owner is what will be using the state machine, and currentState is obviously what state it is currently in.

State Class (within StateMachine script)

There were several abstract methods created for this class. These were: EnterState, ExitState, and UpdateState. EnterState allows you to perform actions immediately upon entering a new state, ExitState performs actions necessary when leaving a state for another, and UpdateState performs the various update actions for that state on that object.

FirstState

This class inherits the State class in the StateStuff namespace. The State here takes in an AI reference (again, I need to look into this more to see what this is actually doing). I see what this is doing better after implementing the abstract class. The type that is passed into State is then the type required by all of the methods that take in a parameter of type T. So since we declared State, now all of the methods require an input of AI _owner (translated from T _owner).

Their general idea is that there is only one instance of each independent state class, and every object that wants to use this state will just reference this same single instance. Following that, they use a bit more of an involved singleton-looking pattern to create this. The setup is the following:
public class FirstState : State
{
private static FirstState _instance;

private FirstState()
{
if (_instance != null)
return;

_instance = this;
}

public static FirstState Instance
{
get
{
if(_instance == null)
{
new FirstState();
}

return _instance;
}
}
}

The second state is exactly the same as the first, it just changes some of the text around so that it matches the new class name.

AI Class

This class represents the main script that would be running on your object that you would like to be using AI. To show the state machine working with it, it simply has a timer in the Update method that changes a bool.

GENERAL FLOW

There is one StateMachine instance and one instance of each individual state class. Each state has an UpdateState method, which generally corresponds with what an object in that state should be doing with an Update method. This is actually called through the StateMachine’s Update method though for every object.

The class which you want to use with the StateMachine and various States (AI in this example) must first reference the StateMachine and pass itself in as a paramter. Then it just needs to make sure to call stateMachine.Update within its own Update method. This is what allows everything to communicate what an object using this state machine should actually do in that state.

Finally, each individual state class is responsible for determing when to change to a new state, and what that new state should be. This is however performed by using the ChangeState method found within the StateMachine class. This method is responsible for calling the ExitState method from the old class, and the EnterState method from the new class.

FINAL NOTES

This setup uses a single instance of a state machine and a single instance for each state, which can be a nice avenue to take since it can really keep things scaled down that way. It also seems nice that the classes simply using this StateMachine setup mostly just need to call the StateMachine’s Update method to really interact with it. It helps keeps them from getting messy with state machine code. It does seem like it could be a bit tricky making sure the individual states themselves have proper references to check within the AI classes to figure out when they should change states with this approach.

AI State Machine Tutorials: Tutorial #3

September 25, 2019

Tutorial #3

From Blog Post: Unity Basic AI State Machine Tutorials

Youtube – ADVANCED AI IN UNITY (Made EASY) – STATE MACHINE BEHAVIORS

Tutorial #3

By: Blackthornprod


NOTES

This tutorial actually dealt with using the Unity Animator to create a sort of state machine setup. You can add behaviours to animation states, which are already setup in a very similar way to the last AI State Machine tutorial I did from Joey the Lantern (Tutorial #2 in this recent tutorial list).

These behaviours already have methods such as OnStateEnter, OnStateExit and OnStateUpdate (as well as several other more animation focused methods). This tutorial uses these to setup the logic for their state machine.

While this seems nice for getting something running very quickly, especially from an animation focused perspective, I think I would rather use the setups from the other tutorials that start more from scratch and allow you to develop the full system yourself. I would much rather follow Tutorial #1 and Tutorial #2 than this one.

Unity AI with Basic State Machine

September 24, 2019

Basic State Machine Setup

Unity Tutorial

Youtube – Unity3D AI with State Machine (FSM), Drones, and Lasers!

Tutorial #1

By: Unity3d College


Tutorial #1

This tutorial goes over a “good” version and a “bad” version of setting up state machines. The bad version will work, and is ok for very small scale projects and objects, but it does lack scalability and has some poor design choices going on.

The real state machine covered in this tutorial is not a monobehaviour, but is still able to access components of objects. This was a point they wanted to make sure they covered with the laser object reference.

To start going over the state machine, they go through the Drone class and its variables. Target is a public Transform but has a private setter. The Team variable Team uses an expression body property to allow the setting of team from the inspector without letting anything else change it.

The next class they go over is the StateMachine class. This starts with a dictionary that contains all of the possible states. It takes in a Type and a BaseState value. The Type is just type of the state class, and the BaseState is a new object of that specific state.

The Update method of StateMachine first checks if there’s a current state. If there is none, it sets a default state. It then performs a method called Tick to determine what the next state is (if it is either the same state again, or a new state). It then checks if the nextState is a different state, and if so, switches to the new state.

Each state has had its own class created, each of which inherits from a public abstract class called BaseState. None of these are monobehaviours, but you can still pass in a GameObject object through any state which gets set to a GameObject variable in the BaseState so the states know which object to control. This BaseState also uses protected variables so that classes that inherit from it may use them, without allowing anything else to access them. And finally, BaseState has a public abstract Type Tick method just to make sure every state class has a Tick method (actions to have an object perform in this state).

While checking through the individual state classes, they mentioned the use of nullables. You can add a “?” to the end of a variable declaration to make it nullable. This allows you to set that variable to null when you normally cannot. They like to do this just as a consistent way to help them check if something actually has had a value assigned to it or not.
Example:
private Vector3? _destination;

They also setup a GameSettings class to help them change general variables that go along with their state machine. This uses a simple singleton pattern setup like the following example:

public static GameSettings Instance { get; private set; }

private void Awake() {
if (Instance != null}
Destroy(gameObject);
else
Instance = this;
}

Unity Basic AI State Machine Tutorials

September 23, 2019

Basic AI State Machines

Unity Tutorials

Youtube – Unity3D AI with State Machine (FSM), Drones, and Lasers!

Tutorial #1

By: Unity3d College


Youtube – Unity 3D – Make a Basic AI State Machine

Tutorial #2

By: Joey The Lantern


Youtube – ADVANCED AI IN UNITY (Made EASY) – STATE MACHINE BEHAVIORS

Tutorial #3

By: Blackthornprod


State machine is just a term I have come across when researching and working with AI projects, so I wanted to delve into it a bit more to understand it better. It is my hope that this will be useful as both game design experience as well as general programming experience. These tutorials I grabbed are mostly from well know Unity devolepers that put out generally good learning content, especially when it comes to the programming side.

I am also looking to take a general AI course and do some more advanced AI work in my thesis, so it makese sense to start finding some more interesting or well defined AI systems and learn how they are made. These tutorials are relatively all on the shorter end as well, so should be easy to knock them all out in a single session.