UFSM: Finite State Machine

That is a demo project, there’s no plugin in there since I agree to publish the tool through Marketplace environment.

I personally only create states and assign events through C++ for my functions; I use Blueprints for very little things, like an end point thing…
In C++ is pretty straightforward to bind functions to state changes, but for Blueprint users I was expecting them to use the Animation Blueprint graph (the first team using this plugin is doing exactly this, AnimBP controls everything) to control their states so I didn’t really expand on Blueprint dispatchers and I’ve left the “switches” as an option for more freedom in hands of Blueprint coders.
I will investigate automatic event bindings to not force you creating dispatchers or switches, but so far I didn’t think of any “non-intrusive” way of doing so.

There are studios owned by companies such as Sony and Microsoft currently using this FSM plugin, I’ve been focusing on following what they have demanded from me and a certain level of freedom have always been a concern; If I see there’s a way to create automatic bindings for Blueprint environment without forcing everyone to work under the exact same paradigm then I can add it, no problem.
Currently the most effective way of making use of this system is if you have both a C++ programmer (creating FSM states, events and rules) and the Blueprint designers simply implement whatever the code needs when the FSM switches to that state usually triggered by underlying C++ code somewhere.

@zickig Okay… I have added an alternative setup for you to avoid the whole “SWITCH on Enum” stuff.
This will be available on 1.5.5 update, for Unreal 4.15+;
This method uses Unreal’s UProperty reflection system to automate allocation of State functions for your FSM Blueprint, so it is going to cost you something around 0.2ms from your Game’s framerate.

To use it, go to Project Settings panel and on the General Settings for the FSM plugin you’re going to find this option, “Blueprint Auto Flow FSM”:

Besides naming your Blueprint’s functions correctly, without typos, that’s all you have to do; no more Switch statements;
The reflection system assumes you have created functions that follows the “On Begin”, “On Update” and “On Exit” + State name convention.

So, if your FSM has a State named “Reload Ammo”, then the reflection system will expect from you to create the functions it is going to call; they are space agnostic:

On Begin Reload Ammo
On Update Reload Ammo
On Exit Reload Ammo

or

OnBeginReloadAmmo
OnUpdateReloadAmmo
OnExitReloadAmmo

both are going to work properly; but mixed naming convention won’t work, such as:

OnBegin Reload Ammo

The reflection system will ignore it if you name your State functions like that.

Limitations; currently this will **not **support binding Blueprint functions that contains input parameters.
For example, my jump function requires to know which was the last State ID before performing any actions; but the reflection system will not process parameters, it will give you this error instead:

My workaround was simple, I’ve used OnBeginJump event function as a wrapper instead:

And the results are all the same as using a Switch statement on an Enum:

This will set you free from the “switch statement mess”… But, if you commence mistakes it will be harder for you to debug your errors :slight_smile:
I’m sending 1.5.5 to Marketplace team this next Friday, cheers!

1.5.6 Released

[UFSM 1.5.6] {UE4.15+}

  • Improved compatibility to PS4 platform.
  • Improved ‘Blueprint Auto-Flow FSM’ functions.
  • Added ‘Generate Functions’ button to the FSM Details panel, creates Blueprint Functions for all your FSM States with a single click.

An important note about the “Generate Functions” button:

That only works on your FSM Components you have created a Blueprint for it!
If you use the default raw StateMachine Component, without creating a Blueprint, that won’t work because that base Component is pure C++, there’s no parent Blueprint asset for it.
So, to generate functions for a Component, create an Asset, right click Asset Browser and create one FSM Component Blueprint from this menu, then “Generate Functions” and “Blueprint Auto Flow FSM” will work as expected:

Once you have your Blueprint FSM created, you can add it to your Actor from the “Custom” Component section:


Open the FSM Component Blueprint asset and there follow steps from gif above, now it works :wink:

  • Create your States list. compile Blueprint.
  • Click the “Generate Functions” button.

If you want to trigger the functions without Switch events, enable this in Project Settings:

Someone asked how to make a Blueprint react to a State change from another, different, Actor Blueprint;

FSM Components have builtin Event Dispatchers. You can get the FSM Component reference from other Actor and subscribe to its Event Dispatcher, like this:
(Do the same for OnUpdate and OnExit)

C++:



OtherActor->StateMachine->GetState(uint8 Id)->OnBeginState.AddDynamic(this,&AThisClass::OnSomeStateBegin)


UFSM 1.5.7 {UE4.15+}

Released

1.5.7 introduces a built-in Message Interface + Delegate Dispatcher to assist you with the process of binding your functions exactly the correct time after the FSM Component has been fully initialized.
Currently, we rely on event Begin Play to do this which is relatively unpredictable the more the project grows… We end up using Delays in Blueprints and hoping the Components have been already initialized, BP Interface will solve that unreliability.

On 1.5.7 your FSM Component have this native ‘FSM Interface’ built-in:

Whenever you want to react to the initialization of a FSM Component, you can implement this Interface into the interested Actor and it will automatically receive an Event from the FSM telling this Actor when it’s ready, fully initialized:

Once your interested Actor has the Interface added, it can now listen to FSM initialization events and grab a reference to the FSM that just finished initializing:

And an example of binding the Level Blueprint to OnBegin event from the Player Character’s ‘FSM Input’ when that specific FSM Component has finished initializing its States:


In 1.5.7, on C++ you’ll be able to safely initialize your FSM like this:



virtual void InitializeFSM() override;

void UMYStateMachine::InitializeFSM() {

	Super::InitializeFSM();

	// Bind your functions to States here...

	GetState(*ID*)->OnBeginState.AddDynamic(this,&UMYStateMachine::OnSomeStateBegin);
	GetState(*ID*)->OnUpdateState.AddDynamic(this,&UMYStateMachine::OnSomeStateUpdate);
	GetState(*ID*)->OnExitState.AddDynamic(this,&UMYStateMachine::OnSomeStateExit);

}


And subscribe to its initialization from another Actor like this:



void AThisClass::PostInitializeComponents() {
	OtherActor->StateMachine->OnInitialized.AddDynamic(this,&AThisClass::OnOtherActorFSMCompletedInitialization);
}

void AThisClass::OnOtherActorFSMCompletedInitialization(const UStateMachineComponent* Context) {

	if (Context != OtherActor->StateMachine) {return;}

	// Now we know that the another FSM is fully initialized, so now we can safely bind to its States...

	OtherActor->StateMachine->GetState(*ID*)->OnBeginState.AddDynamic(this,&AThisClass::OnOtherActorFSMStateBegin);
	OtherActor->StateMachine->GetState(*ID*)->OnUpdateState.AddDynamic(this,&AThisClass::OnOtherActorFSMUpdate);
	OtherActor->StateMachine->GetState(*ID*)->OnExitState.AddDynamic(this,&AThisClass::OnOtherActorFSMStateExit);

}


UFSM 1.6.0 {UE4.15+}
Release for 4.15

  • Hierarchical FSM Component (HFSM) has been removed; the reason for that is: it wasn’t really useful enough to maintain.
    We can still attach FSM Components to an Actor and use the “Go To FSM” Node and the results are exactly the same,
    so the HFSM Class isn’t really useful at all and to reduce code complexity I’ve decided to scrap it out.
    The only things HFSM was adding were more labor and more impact to performance which isn’t good to have.

  • Fixed typo “succeded” in FSM_Transition.

  • SetState functions no longer execute when the FSM Component is set deactivated.

  • FSM Visualizer panel now displays additional info; (this panel is there mainly for visual communication with non coders);

  • Panel will also now track some real-time behaviour when picked a FSM Component’s Blueprint while playing in Editor:


[Blend State Machines]:

  • Easy way to blend two separate Animation State Machines or Cached Poses without modifying the
    original Base Pose of the Skeleton; Works from any Animation Blueprint Class. Usage example:

[Set State]:

  • Sets a FSM Component’s State based on target Animation Blueprint’s State Machine.
    This new function allows developers to manipulate and sync Animation States to Blueprint
    FSM Components without requiring you to reparent your Animation Blueprint.
    Works from any Animation Blueprint Class. Usage example:


  • Added Replication Notify Functions that you can override in Blueprint or C++ to invoke custom replication behavior:

[On Rep State ID]:

  • Notify fired by a FSM Component when relevant owner Actor receives replicated State ID value:

[On Rep Previous State ID]:

  • Notify fired by a FSM Component when relevant owner Actor receives replicated Previous State ID value:

[On Rep State Time]:

  • Notify fired by a FSM Component when relevant owner Actor receives replicated State Time value:


  • Source code fully reorganized to uptimized headers, paths and compiler build time.

Awesome! I bought it. It’s great!

Example of how to initialize an FSM Component in C++ using the new API from UFSM 1.6.0 without losing your Dynamic Bindings after the Component have been initialized:

A Simple Character .H:



#pragma once

#include "UFSM.h"
#include "GameFramework/Character.h"
#include "FSM_NativeCharacter.generated.h"

UCLASS()
class MYGAMEAPI AFSM_NativeCharacter :  ACharacter,  IFSMInterface
{
	GENERATED_BODY()

:
	// Sets default values for this character's properties
	AFSM_NativeCharacter();

	UPROPERTY()
	UStateMachineComponent* StateMachine;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

	UFUNCTION()
	void BindBeginIdle();
	UFUNCTION()
	void BindUpdateIdle();
	UFUNCTION()
	void BindExitIdle();

:
	/// FSM: Initialization Interface.
	UFUNCTION(Category = "FSM", BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "FSM: On Initialized", Keywords = "FSM Initialization Interface"))
	void OnInitializedFSM(const UStateMachineComponent* Context);
	//
	/// FSM: On Any 'On Begin' Event.
	UFUNCTION(Category = "FSM", BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "FSM: On Any Begin", Keywords = "FSM Begin Event"))
	void OnAnyBeginState(const UStateMachineComponent* Context, const FName WithStateName, const uint8 WithStateID, const uint8 WithPrevious);
	//
	/// FSM: On Any 'On Update' Event.
	UFUNCTION(Category = "FSM", BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "FSM: On Any Update", Keywords = "FSM Update Event"))
	void OnAnyUpdateState(const UStateMachineComponent* Context, const FName WithStateName, const uint8 WithStateID, const float WithStateTime);
	//
	/// FSM: On Any 'On Exit' Event.
	UFUNCTION(Category = "FSM", BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "FSM: On Any Exit", Keywords = "FSM Exit Event"))
	void OnAnyExitState(const UStateMachineComponent* Context, const FName WithStateName, const uint8 WithStateID);
	
};


A Simple Character .CPP:



#include "FSM_NativeCharacter.h"
#include "Unreal_FSM.h"

AFSM_NativeCharacter::AFSM_NativeCharacter()
{
	PrimaryActorTick.bCanEverTick = true;

	StateMachine = CreateDefaultSubobject<UStateMachineComponent>(TEXT("StateMachine"));
	if (StateMachine->IsValidLowLevelFast()) {
	
		StateMachine->AddState(0,FName("Idle"));
		StateMachine->AddState(1,FName("Stand"));
		StateMachine->AddState(2,FName("Run"));
		StateMachine->AddState(3,FName("Push"));

		StateMachine->SetActive(true,true);
		StateMachine->bAutoActivate = true;
		StateMachine->Debug = true;

	}
}

void AFSM_NativeCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	FSM_Transition Trans;
	StateMachine->SetStateID(0,Trans);
}

void AFSM_NativeCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	
	FSM_Transition Trans;
	if (StateMachine->GetTime() > 4 && (StateMachine->GetCurrentStateID() < StateMachine->GetLastStateID())) {
		StateMachine->SetStateID(StateMachine->GetCurrentStateID()+1,Trans);
	} else if (StateMachine->GetTime() > 4) {
		StateMachine->SetStateID(0,Trans);
	}
}

void AFSM_NativeCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}




void AFSM_NativeCharacter::OnInitializedFSM_Implementation(const UStateMachineComponent* Context)
{
	if (Context != StateMachine) {return;}
	//
	StateMachine->GetState(0)->OnBeginState.AddDynamic(this,&AFSM_NativeCharacter::BindBeginIdle);
	StateMachine->GetState(0)->OnUpdateState.AddDynamic(this,&AFSM_NativeCharacter::BindUpdateIdle);
	StateMachine->GetState(0)->OnExitState.AddDynamic(this,&AFSM_NativeCharacter::BindExitIdle);
}


void AFSM_NativeCharacter::OnAnyBeginState_Implementation(const UStateMachineComponent* Context, const FName WithStateName, const uint8 WithStateID, const uint8 WithPrevious) {/*...*/}

void AFSM_NativeCharacter::OnAnyUpdateState_Implementation(const UStateMachineComponent* Context, const FName WithStateName, const uint8 WithStateID, const float WithStateTime) {/*...*/}

void AFSM_NativeCharacter::OnAnyExitState_Implementation(const UStateMachineComponent* Context, const FName WithStateName, const uint8 WithStateID) {/*...*/}




void AFSM_NativeCharacter::BindBeginIdle() {
	UE_LOG(LogTemp,Warning,TEXT("{FSM}:: %s"),TEXT("BINDED Begin!"));
}

void AFSM_NativeCharacter::BindUpdateIdle() {
	UE_LOG(LogTemp,Warning,TEXT("{FSM}:: %s"),TEXT("BINDED Update!"));
}

void AFSM_NativeCharacter::BindExitIdle() {
	UE_LOG(LogTemp,Warning,TEXT("{FSM}:: %s"),TEXT("BINDED Exit!"));
}


Making use of “IFSMInterface”, and its “OnInitializedFSM” Event, this way it’s possible to keep alive your C++ State Bindings even after someone have made changes to States on the Blueprint Component inherited from your C++ base class.

Hi.
When I’m creating an asm inside the animation blueprint and adding some states in it, should they automatically update FSM component state list or I have to put them by the hand?
Anyway, that’s great plugin!
Thanks.

The Animation Blueprint’s State Machine will automatically repopulate (replace) all the States list on your FSM Component if you set ‘override FSM’ to true on your AnimGraph details panel.
That is if you are using StateMachineAnimBP as a parent class, otherwise it will not replace the States list you have on your FSM Component.

Hmm… that’s odd because I’ve made it exactly as you told.
As example I’ve made a blank c++ project, and added bps + fsm components to it. At anim bp I’ve created new state machine with few states, set target fsm and asm in class defaults, but still nothing gets updated in fsm component.
However, if i’ll add states by the hand with exact same name as in animation bp’s state machine, everything works great (it’s ok for me but I was a bit confused at first after the purchase). Is there a bug or I’m missing something, could you please take a look?
Project download link: Microsoft OneDrive - Access files anywhere. Create docs with free Office Online.

I’ve tested your demo project and it all works… the FSM Component prints on top of panel “TestStateOne”, just like the State created inside your AnimBP.
Which means the AnimBP has successfully overridden the States in the Component (but they won’t show in the Blueprint Details panel because the override happens at runtime only).

If you mean to set the State of an AnimBP from the FSM Component, we can’t. Epic has locked this functionality and I am waiting for them to fix it before making possible to sync AnimBP States from a FSM Component:

https://github.com/EpicGames/UnrealEngine/pull/3515

Ah, okay, nevermind :slight_smile: Your plugin is great!
It took me a week to rewrite my past character bp from scratch using ufsm and it was incredibly flexible. No spaghetti, no ridiculous switches, branches etc to check the possibility of performing some specific actions. Previously it was very time-consuming for me to add some new functionality such as cover system or parkour. And with every new feature it was getting harder and harder to add stuff. But with ufsm I can make it much faster. And ****, it looks neat. Sweet!

Hello! Firstly, thank you for this awesome time saving plugin (that really should just be a part of the engine!)
Would it be possible for you to add (if you have time of course) a function to cancel the current transition, for example in-between an OnExitState and OnBeginState events? This would be a greatly appreciated functionality. I require the ability to check if the state can even be exited before checking whether or not the next can be entered. I’m sorry if this already exists and I have missed it, but I could not locate any manual way of stopping a transition. Thanks in advance!

I usually script these rule checkers inside of the OnExit function itself, so I’d need a somewhat photoshopped concept screenshot of what you aim for; do you mean a “conditional set state” node which cancels the transition in case the condition is not met, just returning to the state already set?!
There are many different ways of doing what you say, thus I need more specifics.

Pretty much this, yes. Basically inside of the OnExit function I would like to have the ability to cancel and stay in the current state. That said, a conditional set state node would also be very very useful.

OK so here is an example of my current situation.

Now I know with the blueprint implementable events that it would not be possible to cancel in time due to the nature of how they work. The function you suggested would eliminate the need to use the above workaround (which as a side effect ends up resetting the state timer for obvious reasons.)

Okay, I have to finish a SQL Server service app I was given the task to build and then I will look into this;
I’ve added this to my to do list and will begin studying a solution in few hours once I finish this one db task I’m working on.

If I expose the Fsm_Transition struct the way I’m thinking of doing it, you will be able set the transition rule based on conditions you code so if the trans return an “Aborted” state then the Exit trigger can be canceled, not resetting or re-entering actual state.

This sounds perfect! Thanks :slight_smile: