UFSM: Finite State Machine

What I can do easily, without breaking anything, is implement “latent” versions of “Finish State” BP Node which is used already to invoke Default Transition…

These nodes can implement the components you mention be needed, timers, callbacks, etc.
With a combination of properties above to a conditional check, Fsm goes to either State A or B… With a callback to either Event A or Event B.

It’s doable, I will add this to todo list.
The small annoyance is these nodes are more friendly to Blueprint FSMs and not so much to pure Cpp Components, but will cover the issues well enough.
​​​​​

Sounds good! I don’t see myself using it much in C++ anywho, but that’s just me.

Any thoughts on how to fix that corrupt(?) state?

You can loop through the TMap container of States and check for validation… If any is null/invalid create a new State struct and assign to that index.

Btw, whenever you change your Array of ‘FName’ States, add/remove/replace, etc… Make sure you call the “MakeStates()” function.
There is where State objects are generated and stored in the TMap.
You can also force the TMap to create a new State object in the problematic index:



STATE.Add(1,TEXT("stateName"));



Edit:

Actually what seems to be invalid is the “Name” variable of your State object in index 1.
If was the object struct it would’ve crashed earlier, not in that line.

@Vaei

So, I’ve added these new nodes and will send updated plugin to Epic soon…


[HR][/HR]

The situation you describe above could be dealt with doing something like this:

To avoid wasting time creating Event signatures, instead of creating an Event manually, drag from the new Latent “Finish State” Node and the signature it accepts will automatically apply when you create an Event attached to it:

[HR][/HR]
Note however that Async nodes won’t work inside Function graphs, must be onto main graphs and you can’t call them directly from outside the FSM Component’s Blueprint…

The “On Begin Equipping” function should make a call to a custom Event on main Graph to execute the latent Finish node.

For the record I’m doing the state machine stuff entirely in BP. All C++ does is find a reference to the state machine and check the state/set the state in a few cases. The items themselves that make use of the state machine still use a lot of C++.

As for MakeStates() after FindComponent succeeds it actually calls SetupStateMachine() which calls MakeStates().


void AVESItem::PostInitializeComponents()
{
    Super::PostInitializeComponents();

    StateMachine = FindComponentByClass<UStateMachineComponent>();
    if (StateMachine)
    {
        StateMachine->SetupStateMachine();
    }
}

STATES are all valid before and after MakeStates(), it’s being invalidated somewhere else.

And - Awesome, the new nodes look really good

Try change the source code of “Make States” function to something like this and see if the problem still persist:



void UStateMachineComponent::MakeStates(const TArray<FName> &NewStates, FSM_Transition &Transition) {
    if (NewStates.Num()==0) {
        Transition = FSM_Transition::Aborted;
        LOG_FSM(Debug,GetOwner(),this,ESeverity::Error,FString("'New States' Array is zero sized."));
        LOG_PIE(Debug,ESeverity::Error,this,FFIND(TEXT("MakeStates")),FString("'New States' Array is zero sized."));
    return;}
    //
    for (auto &State : STATE) {
        State.Value.OnBeginState.Clear();
        State.Value.OnUpdateState.Clear();
        State.Value.OnExitState.Clear();
    } STATE.Empty();
    //
    for (int32 I=0; I<NewStates.Num(); I++) {
        if (!NewStates*.IsValid()) {LOG_PIE(Debug,ESeverity::Error,this,FFIND(TEXT("MakeStates")),FString::Printf(TEXT("Name for generated State of index {&i} is invalid."),I)); continue;}
        if (NewStates*.IsNone()) {LOG_PIE(Debug,ESeverity::Error,this,FFIND(TEXT("MakeStates")),FString::Printf(TEXT("Name for generated State of index {&i} is invalid."),I)); continue;}
        STATE.Add(I,NewStates*);
        STATE*.Owner = this;
    } Transition = FSM_Transition::Succeeded;
    //
    LinkStates();
}


If still the same, might be something hidden inside State struct constructor.

No such luck. At this point I’ve resorted to rebuilding the state machine, but I’ll keep the old one for testing as long as I can because finding the solution would stop it reoccurring.

[unrelated] The code that changes the initialization process that you gave me before - do you think you could integrate it into the plugin with an option to use it or not? (so that if you update the plugin I don’t have to keep putting the change back) - perhaps a selfish request but maybe other people would use it also.

Yes, I’ve added it to the code.
I’ve also added debug code to check if an internal State object is invalid or is its internal Name that is actually corrupted…

Can I send you this project to see if you can find the issue with the invalid state? If so PM me your gmail so I can give you access to a zip on Google Drive.

You’d need to build it in VS2017 (4.19) for “DebugGame Editor”, press F5, hit play in editor. Then press “F” which will pick up an item, and then crash.

I can send you modified version of Plugin with extra debug code I’ve added, but at this moment I will not be able to examine projects (I’m working for someone else right now).
In few minutes I will pack new plugin version and PM you a link, hopefully the changes solves the problem or help you identify what happened to your index “1” there.

Hmm, no difference. What is the extra debug code expected to do?

So the do-over has the same issue this time. Both occur with the ‘Equipping’ state and it happens following the success of the ‘FSM: Set State’ node going to “Equipping”. I can connect “Succeeded” to a loop printing everything from the STATE TMap (I exposed it to BP for debugging) and they all print fine then proceeds to crash (immediately) from the Update function.

Does the State name “Equipping” appears on the panel when you click the “Visualize FSM States” green button??
Also, this happens every time no matter where you call it from?!

Btw, if you comment out the event causing the crash, would maybe fix this… but the problem is we both don’t know yet why this is happening in your project.
If you execute Broadcast of events within PostInitProperties when the Game World is invalid this kind of crash might happen, but in this case it’s unclear why that broadcast crashes there for you.

Sure does!

However, I’ve found more info. It only occurs when calling “Finish State”. The transition is specified (as you can also see in the visualizer).

It is not only “Equipping” that Finish State (and the exact logic shown) is used for - it’s used for several and works for all other states. However, if I tell it to ignore the “Equipping” state in the logic that calls Finish State and instead use the same logic with a Set State node in “On Update Equipping” it works fine (but only with a Set State node, if I use Finish State here it will also crash in the same place). Which means the Finish State node is somehow related to it.

Debugging “Finish State” shows that it calls SetState successfully. Passes the correct StateID to Enter(). Calls all the On Begin State delegates, meanwhile the STATE TMap is all still valid (no invalid Equipping state). Then the update tick crashes it.

https://i.imgur.com/id3aN0P.png

https://i.imgur.com/O7geLTR.png

Oooohhh ok…
Then the problem is possible to be your “(Mixed Flags)” values in there.

Clean up all “Rules” flags from all defaults links and please tell me if this problem still happens…
One of those Rules might have invalidated the State object by the time that event in Update is reach.

For some reason Unreal Engine is automatically applying first Rule value (create state)… It shouldn’t do that at all.
Flags should be clean by default.


The team who requested those flags aren’t even using them anymore, so I will probably just remove them to reduce complexity.

Thank you!! Removing the flags fixed it. I didn’t even take note of them :frowning: Definitely very destructive that they’re on by default and as you say, blueprints sometimes have weird defaults that you can’t seem to get rid of especially where structs are concerned.

Yeah, this is new…
Unreal Engine didn’t do this on earlier versions. by default the flags were simply (none).
Anyway I will just remove those flags, they were implemented before them async nodes existed. (they do the same thing anyway)

Thanks again for your wonderful support :slight_smile:

Hi, the code I had stopped working after the last update, the “Begin” function works, but the “Update” stopped working.

Any idea of what could have happened?

I’m using blueprints on 4.18.3