# States

The States module will help you manage your player and world states while preventing conflicts between them.

There are 2 subsystems related to states added by the plugin:

  • User States: a Local Player Subsystem which will manage a state system for each Local Player in your game.
  • World States: a World Subsystem which will manage a single state system for the current World.

# Some Use Cases Example

I'll start by exposing you a simple yet common use case in many games.

Let say you have a player character that can roam around the world, and there may be sometimes some dialogs popping up when talking to NPC characters, and the player may show a pause menu at any time when pressing a button. For both cases you want to disallow your player to interact with the world during those states.

When a dialog pops out, or when the player resume the game, you want now your player to be able to interact with the world again, of course.

However if you re-allow world interactions when resuming game while the pause menu has been opened during a dialog, then your player can interact with the world when it should not be allowed!

Here comes this plugin, by defining some states like Playing State, Dialog State and Menu State, they allow you to switch state and define behaviors to each state, for example, by allowing world interactions when entering the Playing State and disallow when exiting it.
No state other than the Playing State should touch the world interaction toggle, thus you are sure to always enable it in the proper state.

# A Stack-Based State System

The state system is based on a stack, meaning you push a new state on top of the others, and you pop a state from the top of the stack.

# Lifecycle of a state

The state life is made up of those different functions:

  • Init: Initializes the state at its creation when pushed, you can pass some parameters when calling Push State from the subsystem.
  • Enter: Called when the state become active. You have access to the previous active state (From State input).
  • Tick: Only available for World States! Same behavior as the actors Tick events.
  • Exit: Called when becoming inactive (when state is popped or another state is pushed on top). You have access to the next active state (To State input).
  • Release: Cleanup must be done here if necessary, the state is no longer alive and may be Garbage Collected at anytime after that.

You can refer to the diagram beside to know when each one is called relatively to the others when doing a push or pop (time passes from up to down).

* Tick function exists only for World States.

# Getting Started

# What are User States

I call "user" states a local physical player state. Since the Player State is already existing in UE for a whole another topic, I decided to use the word "user" instead of "player".

You should use them for states on the scope of the player, mainly what are client-side only.
For example, a dialog with an NPC, or going into the game settings menu.

# What are World States

This state stack is unique for the whole world.

# Create Your States

To create a new state, just create a new blueprint class, and search for CX State.

You can then override its functions to define its behavior.

# Push and Pop your States

For the World States you just have to call the Get Subsystem node, then call the Push State function on it and finally choose the World State class you want to push.

To pop a state, the best way is to keep a reference of the state you've pushed, and pass it to the Pop State function.

# How to pass Parameters to your States

Any UObject derived class can be used as a parameter. So you can pass an Actor or a PlayerController if you want.

However I prefer to always create a custom UObject class used only for parameters, so you can reference your Actor or any other object, and you can add more parameters too, and easier to maintain too.

So, here is my preferred method to pass parameters to a state.

First, create a new blueprint class with UObject as parent and add all your parameter variables in it.

After that, before you push a new state, construct a new instance of your param class with your parameters filled in, and pass it to the Push State node.

Finally, you can access it in the Init event of your state, you just have to cast it to your blueprint class, and then you can get your parameters!