Hello everyone! I’m here to share this tool to help you manage the logic of your characters by using states, it’s very simple but I hope it works for your projects.
The following image shows the relevant nodes you’ll need. The “FSM” node is required in order to access the States enumerator, which will be used with a “Switch on” node, notice that it needs to be connected to the Add State and Set State macros. The “Add State” macro is the brain of the state machine and is needed every time you create new states, every time you enter a state you can print it on screen, you can also print the time passed since the state is active, the On Enter execution output only fires one frame and could be useful to set initial values for that state, the On Update fires every frame, here’s where you do the logic and your checks to change to different states, the On Exit fires one frame, could be useful to reset some values when you leave that state. You can query the current and previous state, the “Not Exit” bool is useful to prevent conflicts with the controller inputs in a state, I will explain more about this in the next tutorial. I hope this helps someone, any comments/feedback are welcome.
[spoiler]We’ll start by creating a new project using the Third Person template, now let’s unzip the file in your project’s content folder.
In you content browser you will see the FSM folder, inside is an enumerator.
here is where you add new states, let’s double click to add a few of them.
Let’s open the ThirdPersonCharacter blueprint and add a new component, type “FSM” and select it.
If you select the “FSM” component, in the details panel you can see the “States Enum” enumerator, the ideal thing to do would be to choose your initial state from here, but in the current build 4.14 there is a bug that ignores when you choose default values for enums, so we need a workaround.
Let’s add an Event Begin Play, drag the “FSM” component to the graph and from the node get the “Set States Enum” enumerator node and set it to any initial state you need, in this case we need “Idle/Run”
Get a “States Enum” from the “FSM” node, add a “Switch on StatesEnum” node and connect it to an Event Tick.
This was the initial setup for our state machine, now let’s add our first state, drag a wire from the “Idle Run” execution output, type “Add State” and hit enter.
The default behavior of the Third Person Template basically is to move, idle and jump, but there is a problem with this, if you try to move in the air, the controls for movement are still responding, allowing your character to rotate in the air and even change the impulse direction, In our case we don’t want that behavior, so let’s fix that, now let’s link all the nodes responsible of making our character move to the idle/run state. Next we are going to do something I like to call “Filter Controller Input Events”, which consist on creating custom events that we are gonna call in a “Switch On” node. So, let’s create two custom events, one for “Move Forward” and the other for “Move Right” input events.
Let’s add a float to each custom event that will pass the axis value of the original input events.
Now let’s connect the custom events to the “Add Movement Input” nodes, the originals should be connected to a “Switch on StatesEnum”, and let’s call the corresponding custom event functions. Now the movement input is linked to the Idle/Run state.
Let’s do the same for the Jump input event.
Here is where we use the “Not Exit” bool, which will be helpful to avoid possible bugs when pressing two buttons at the same time, for example, as we are in the idle state, we are allowed to Jump from here, but let’s imagine we also have a punch action, so if I press these two buttons at the same time, it is likely enter in conflict with the “On Exit” execution output, because at that moment the other pressed button can do his actions, I hope I’ve explained well.
We can do the same for the movement input custom events.
It’s time to check if the character is in the air, so we can switch the state to “Jump”, for that I like to create a reference to the Animation Blueprint in the Event Begin Play, this way we can access to all the variables from that blueprint.
If the “Is in Air?” var is true we call the “Set State” macro and from the state enumerator list we choose “Jump”. Don’t forget to connect the “FSM” node to the macro.
As we are adding more complexity to the state it is very useful to collapse all the corresponding nodes into a collapsed graph.
Let’s add a new state macro and connect it to the jump output of the main switch on states, here we use the “On Update” to check every frame if the character is no longer in the air, if true we set the state back to idle.
Let’s test it! now every time you try to move your left stick in the air, you’ll notice that you cannot rotate or change direction.
Now let’s do something wild, create a new state called “SuperJump”, let’s make it so every time you land from air if you hit the jump button right after, it will perform the super jump.
Let’s collapse all the nodes of the jump state into a function, so we can reuse it for the super jump state.
Now create two float variables, “DefaultJump” with a value of “600”, and “SuperJump” with a value of “1200”
Let’s double click the Idle/Run graph, look at the selected nodes, all this do is, every time you press the jump button, it will check if the time is less than 0.1, if true it will set the character’s JumpZVelocity to the SuperJump value, and call the jump function. In case it fails, just calls the jump function. On Update, it will check if the character is in the air, if true it checks if JumpZVelocity is set to the “SuperJump” value and set it to that state, in case not it just calls the regular jump state. On Exit, every time we exit this state we set the JumpZVelocity to the default value.
If we try to play again, the super jump works fine, but there is one problem, every time you land from a super jump the character will do another super jump, let’s constraint it to a jump and then super jump only behavior. To do it we need to know which was the previous state, if that previous state was the super jump then we are not allowed to perform another one, and just a regular jump.