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

Hi, thanks for the great plugin!

I’ve started to integrate it into my project and faced some issues with order of loading game modules. Hope your insight will help :slight_smile:

In general, I have 2 game modules (the 1st is something like core library and the 2nd is game itself) and GCFSM plugin enabled.
In core module I define parent class for blueprints containing state machine, smth like UStateMachine. In game module I create blueprint (let’s say BP_StateMachine) derived from the UStateMachine and define state machine inside.

Issue 1: to make sure that BP_StateMachine asset is loaded correctly we need to load modules in order GCFSM (PreDefault) -> Core (Default) -> Game (PostDefault) otherwise all FSM nodes disappear from BP_StateMachine. So this issue is solved by setting loading phases as mentioned.

Then in core module I define state class (let’s say UState) with exposed member variable TSubclassOf<UExample> ExampleClass (so it will appear as pin in FSM state node in BP_StateMachine). This UExample class is also defined in core module.

Issue 2: There’s “ensure” crash during BP_StateMachine loading (BlueprintCompilationManager.cpp line 1312):


UBlueprint* BP = Cast<UBlueprint>(ForClass->ClassGeneratedBy);
if(ensure(BP)) ...

call from GCFSMStateNode.cpp (line 493):


// Add pins for state arguments
auto execPin = spawnNode->GetThenPin();
if (auto implementationClass = GetImplementationClass())
{
    execPin = FKismetCompilerUtilities::GenerateAssignmentNodes(compilerContext, sourceGraph, spawnNode, this, spawnNode->GetReturnValuePin(), implementationClass);
}

As far as I understand the problem is that no CDO is presented (BlueprintCompilationManager.cpp line 1306) for UState class because core module is not loaded yet.
If I change loading order to Core -> GCFSM -> Game crash disappears but Issue 1 is here again.

For now the only solution I see is to merge core and game modules, but I would prefer not to do that as I’d like to reuse core module in several projects.

Thanks in advance!

@miko1a

That is quite strange indeed. Since you are loading the modules in the order GCFSM->Core->Game, when blueprints in Game starts compiling the Core module is already loaded and I would expect all its CDOs to be available. However the loading phase in Unreal is quite intricate so there may be something I’m missing. Could you please contact me privately in order to establish a direct communication channel (email, Slack or other) to address the issue? Having a test project reproducing the problem would be most helpful.

Sure, thanks!

PS. Turned out that editor is not blocked by this error, you can just ignore it and continue. PIE works fine as well.
But packaging is broken.

UPD: for those who are interested I’ve reported the bug to Epic, see ticket here:

Sorry for spamming again, I have some suggestion and argument for it in 3 pictures:

Unreal has quite hard time with wiring for execute connections in cases like this:

I am trying to connect exit pins from FSM back to beginning. I know adding empty macro there at end would probably help.

So my suggestion is to have something like this:


Ofc, working only in same\single event graph or FSM. This would reduce those spaghetti code problems with execution pins.

Hi @Nawrot, such a control flow node would effectively be equivalent to an general purpose goto. While it may be interesting and I agree that it would simplify large FSMs, its usage would not be restricted to FSMs. If Epic wanted to have this kind of flow control primitive, I believe they would have added it themselves long time ago. I can imagine they won’t do that because it’s a feature that can too easily be misused. Please notice that your example could be easily approached with a WhileLoop node, but you actually can’t do that because the compiler (incorrectly, IMHO) detects an infinite loop… I don’t know the blueprint compiler internals well enough to exclude that, if I were to implement the feature as you described it, it wouldn’t actually be unusable because of automatic infinite loop checks.

Thanks for reply. So i am back to splitting all FSM into smaller ones. They make a lots of things much easier to do, just that spaghetti net of connections triggers my ocd.

Hi, amazing plugin,

I seem to have problem using the “Get FSM Active State” node with a Submachine

The very same node works fine if I’m not using any submachines, but it won’t recognize the state of any of the machines present in the event graph and it will always lead the execution through the “No State” pin.

Is this the intended way to work? or is it a bug?
For now I’m dealing with this by setting a variable with the context object from inside the state, but I’d like to know how I can make it work with the aforementioned node.

Using latest FSM plugin on 4.20.3.

Thank you

Can you explain in detail the state transition object? How to edit it, and is it possible to override callback events(e.g. OnActive when connected state is entering)?

I apologize for the delay. Every time you use the “Get FSM Active State” node, you need to specify the state class. The No State pin is triggered If there’s no active state or if the active state is not derived from the specified class. You usually specify one of your own state classes, but there are three plugin-provided classes that you can safely use:

  1. GCFSMBasicState is the base class for all states: if the FSM is in any state, you will get it
  2. GCFSMState is the base class of all user-defined state classe: if the FSM is in any state you defined, you will get it
  3. GCFSMLocalState is the class for local states: if the FSM is in any local state, you will get it, otherwise you get “No State”
  4. GCFSMSubmachineState is the class for submachine state: if the FSM is in any submachine state, you will get it, otherwise you get “No State”

GCFSMRootState is for internal use and shouldn’t be used with the “Get FSM Active State” node.

What did you put in the State Class pin?

20190130_15h34_32.png

What do you mean with “state transition object”? Do you mean “state implementation class”? For state implementation classes you can override the OnEnter, OnTick and OnExit events.

Is it possible to have the transition events be drawn from an array rather than being ‘hard-coded’ in the blueprints?

Hey there,

any ETA on 4.22 version gamecentric?

Early next week is a reasonable ETA. I will post here when it happens.

Cool, thanks! :rolleyes:

Can you add a node that can be used in an external stop state machine? When dealing with animation and skills, I want to stop the state machine outside.

You can already achieve a similar result by putting your entire state machine in a submachine (tipically a local state machine) and then provide the outer state machine with a transition that stops the FSM.

Thanks you;)

Hey, I think there are some problems with the state class of GCFSMState. If you involve some content of a calculation class, you will quickly expose the problem and its value is invalid.

In my project, I encountered a similar problem, I used the “Copy” node to temporarily solve the crash problem. Is there any idea of repairing this question?

Are there any plans for a 4.22 update? I’ve loved using this in the past and would like it for my current project as well. Thanks

The expressions are evaluated only once when the state is entered and the values are simply used to initialize the corresponding exposed variables of the state object. This behaviour is consistent with the usual behaviour of latent functions, which, incidentally, are used under the hood to implement the FSM. If I understand correctly, you seem to expect the expressions to be re-evaluated each frame, but that’s not the case. If you want to achieve that, I would suggest to use a local state instead.