GC FSM - Event-driven, hierarchical finite state machines in blueprint

I’m starting here a thread support for my plugin GC FSM. Feel free to post here for issues and suggestions about GC FSM. Remember that you can always contact me directly via PM or request an invitation for the GC FSM Support Slack workspace.

Let’s start with an announcement. I’ve submitted version 1.1 of the plugin yesterday. I’ll make a further announcement when it will be published. New things in this version:

  • Support for Unreal 4.18, since I know a lot of you are still using it.
  • New function to pause/resume all the FSMs of a specific context. All FSMs runs on their own tick, because their context might not be an Actor or Component, so it might not have one to attach to. This new function allows to pause/resume this tick. This is done per-context, so all FSMs (and sub-FSMs) of the context are affected. A paused FSM will still receive and accumulate events, but will not process them. There’s also a function to check if the FSMs of a context are currently paused or not, just in case.
  • New function to make FSMs run even if the game is paused. In version 1.0, when the game is paused all FSMs are paused. This is inconvenient if you want a FSM to drive a menu system. With this function you can have FSMs always run.
  • Behaviour Tree integration. FSM and Behaviour Trees can coexist peacefully: now you can start an FSM and trigger FSM events from a behaviour tree using the two newly provided tasks.

I am preparing a new expanded example project showcasing the new features. If you want to try it without waiting for v1.1 to be published, a playable HTML5 version is available. You can even try it without buying the plugin ;).

Version 1.1 of GC FSM is now available on the UE4 Marketplace. Enjoy!

Ok just going through your sample project. In principle, I am starting to understand how it works, but I seem to be missing something obvious. So some questions:

  1. In your example_base: You have a blueprint HIT event that creates a GCFSMTestProjectile. That then triggers an FSM Base Event, with the target SELF and event HIT. What is this HIT event? The same blueprint HIT that triggered it, or is it referencing another event called “hit” elsewhere?

  2. Similarly in the main menu widgit graph: the onClick events for the buttons are trigger an FSM event called Play and Quit. What are these?

  1. The projectile is not created by a blueprint event related with GC FSM. The projectile is created by something (I guess either the character or the player controller) from the sample content I got when I created the project (I used the First Person Template). What happens is that in the ExampleBase blueprint when a collision between the projectile and the cube is detected, a “Event Hit” is triggered by the engine (this is a regular engine event sent by the collision system). In the handler of that event, I just check that the “other” actor is indeed a projectile, since I will receive collision events even when the cube collides with other actors, including the player. If the “other” actor is indeed a projectile, I finally trigger the “Hit” FSM event. I am sorry that the engine-provided name “Event Hit” might have created a confusion, but I believed the name “Hit” for the FSM event was appropriate.

  2. The FSM that drives the menus is located in the ExamplesGameMode blueprint. When the buttons receive onClick events, FSM events are triggered and processed in that FSM. This makes the FSM progress in order to show more widgets or start/quit the game.

Just a note: all GC FSM blueprint nodes are blue-green. The “Event Hit” node in ExampleBase is red, which is the typical color of regular engine-provided event entry nodes. This should help discriminate what is GC FSM-related and what is not.

Ok great that clarified most of it. So for my question 1) above, the FSM event HIT that is triggered is documented where in the example? I was unable to find it anywhere.

Thank you for your feedback. I’m afraid there’s no explicit documentation about the “Hit” event in the project. It seems I should have been more explicit about it, especially since it’s an essential aspect of the example. Allow me to provide some explanation here and I will update the project accordingly. In this particular examples, all FSMs (except the menu one) are declared and run in subclasses of the ExampleBase class. The ExampleBase class is there just to factor some code common among all examples. Take, for example the Example1 class: it runs an FSM named “CycleColors”. When that FSM runs, it eventually reaches the first state named “Green” and execution stops there. Notice that the “Green” state node has a transition event named “Hit”. When a projectile hits the cube, we saw that this causes the execution of the TriggerEvent we were talking about. Since the target of the TriggerEvent call is “self”, an event named “Hit” is sent to all FSMs of the actor. When the “CycleColor” FSM receive the “Hit” event, the “Hit” transition is activated: the FSM leaves the “Green” state and execution resumes, making the FSM progress and eventually reach the “Yellow” state node. From there, the situation repeats: the execution stops and when another “Hit” is triggered the execution resumes reaching the “Red” state and so on.

I hope the situation is clearer now. If you have more questions, do not hesitate to ask.

Hello! Extremely usefull plugin!

I’km using it to running a character behaviour in combat system.

I’ve noticed that there is not possible to trigger a label or something to "force " the FSM to go to apsecific state, like being stunned.

You have to manually add the transition to all of the state, which is kinda boring and bug-prone.
Is there something I’m missing?

Hi Packyman,

Thanks! I would suggest to design your logic in “layers” and implement the design using a hierarchical FSM. In your case the transition to the “stunned” state could be put in a top-level FSM and the “non-stunned” logic in a sub-FSM. The transition to the stunned state would cause any state in a sub-FSM to be exited, without manually putting transitions to each state. State classes could help you re-use sub-FSM logic that may be shared among different states.

This is a nice idea buyt i would suggest to add those kind of triggers for future implementations. Just consider Server controlled FSMs on clients for multiplayer in which Client’s flow should be “adjusted” multiple time by the server, it could be a mess to handle this with transition or hierarchical fsms.

Thank you for your time!

In the latest three year project I worked on, we had a custom-designed FSM system. Someone in the team proposed to have a “set state” feature similar to what you are suggesting. It seemed a good idea at first and the feature was implemented, but in hindsight it was a huge mistake. The feature was quickly abused and lead to a spaghetti design that made the state machines incredibly hard to maintain. The problem was that the FSMs where no longer self-contained and self-descriptive, because the flow of execution could be arbitrarily modified by external sources. Imagine having a nicely structured program and the someone starts injecting gotos from the outside without you knowing. When I started working on GC FSM I wanted to treasure that experience and decided to resist the urge to provide such a feature, but instead propose a better alternative. I believe hierarchical FSMs are that alternative. Together with either state classes or local states, you get a good deal of flexibility. That said, for FSM synchronization between server and client, I agree that it might not be enough. I am aware of the problem and I am actively working on a solution to achieve automatic replication, which will be included in the next release. I hope you will like it.

Hi,

I’m pleased to announce that I have implemented support for FSM network replication. I am now in the process of the final testing and writing documentation for the new feature. The modifications were quite extensive, so my first priority is to not introduce regression in the current feature set. The new feature will be marked as “experimental” until I am sure everything is rock solid, but I am eager to let you experiment with it and hear your feedback! Unless I find anything horribly wrong I am going to submit the new version early next week.

Oh sad! I just managed to make my game work online with the actual version xD!

:smiley: I’m sorry it took so long to implement this feature… but I’m also happy that you found a way to solve your issues!

I will refactor some places but i’ll update to the new version to avoid further problems in the future. When will be online?

it should be online right now.

Hi, I Got a crash in gcfsmutilities.cpp:313. I Connected a delay note to the state’s event pin. It crashed when the function UGCFSMUtilities::GetActiveState is called when the FSM process is in delay. I have read the GCFSM doc that, it shoul return nullptr if I connect a delay note between the states. So I add some code to it, when activeState is nullptr, it return nullptr; Is it that OK?
y the way, GC FSM is very helpful, can’t wait for the new updates. Hope that C++ API will be more powerful in the next version. Thx for reading.

That is the code what I added.

Thanks a lot for the report. You are indeed correct, I should have checked for a nullptr there. However, be sure to set the result variable to EGCFSMGetActiveStateResult::NoState before returning. I’ll the fix in the next release.

As for the C++ API, I am open to suggestions. What do you need that can’t be done right now?