Announcement

Collapse
No announcement yet.

UFSM: Finite State Machine

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • replied
    That worked, the problem was that my VS 2019 was not setup correctly and was not vompiling the project... my bad sorry..

    I am getting this in the log?

    Exit: ]---------->(Standing) at (StateMachineComponent /Game/Maps/UEDPIE_0_TestLevel.TestLevel:PersistentLevel.BP_Player_C_0.Player Stance State Machine)

    Last edited by chiblue3d; 05-02-2020, 12:13 PM.

    Leave a comment:


  • replied
    Set the value in your class constructor or BeginPlay().. or PostInitProperties().
    Try visual studio debugger to check if your class is actually using value = false;

    Depends on how your project is setup, Unreal will serialize the property in your class and changing it in C++ won't do anything.

    Leave a comment:


  • replied
    I set this value on all class UFSM components, however I am still getting the log message

    {FSM}:: ''Blueprint Auto Flow FSM'' is enabled; Trying to invoke ''On Exit'' for (Standing) State, but (OnExitStanding) function have not been found! --> Exit: [Function /Script/UFSM.StateMachineComponent:Exit at (StateMachineComponent /Game/Maps/UEDPIE_0_TestLevel.TestLevel:PersistentLevel.BP_Player_C_0.Player Stance State Machine)]

    m_FSM_StanceState->BlueprintAutoFlowFSM = false;

    Not sure why this is happening?


    Leave a comment:


  • replied
    Thanks I used the BlueprintAutoFlowFSM property and set to false on all my FSM definitions..

    Leave a comment:


  • replied
    myFSM->BlueprintAutoFlowFSM = false;

    Leave a comment:


  • replied
    Sorry for being dumb but how do I get to the "fsm detail panel"?

    Leave a comment:


  • replied
    It's on your fsm details panel.
    a member of the component now.

    Leave a comment:


  • replied
    I just came back to the Unreal engine, not used it for over a year, I finally got my project upgraded to 4.24 (was 4.17) however I am getting the error FSM Auto Flow, I remember this previously and I had to switch off this becuase I was using C++ components not blueprint to handle the states. I am using UFSM version 3 but I cannot find the auto flow option on the settings, did this change? thanks

    Leave a comment:


  • replied
    Originally posted by elisamuelps View Post
    Hello Bruno! I hope all is well with you, just writing because I'm migrating from version 1 to version 3 and there's many game breaking changes (I'm happy to fix them by myself) I'm just confused on where to start appart from the example project. Do you have any videos or a changelog explaining what's new and what do I have to do to use the new FSM version?

    All the best.
    Hello!
    There is an updated demo project here for v3:
    https://www.dropbox.com/s/u9e67i3zkg..._Demo.zip?dl=0

    For C++ samples, there's a few examples posted above in this forum.

    Leave a comment:


  • replied
    Hello Bruno! I hope all is well with you, just writing because I'm migrating from version 1 to version 3 and there's many game breaking changes (I'm happy to fix them by myself) I'm just confused on where to start appart from the example project. Do you have any videos or a changelog explaining what's new and what do I have to do to use the new FSM version?

    All the best.

    Leave a comment:


  • replied
    Thanks. I had a break and got back into it. I have now a complete swing door working in cpp with states transitioning as your example above (only checking owner for data values).
    This is tidy.
    Only "missing" extra feature would be to "visualize" the states graph. "Visualize" in the blueprint does nothing. It would be good to see the states and the transitions (even read-only. no transition redefinition). On click, it could open the function in BP if defined or c++. not sure if it should work like that or if it is not implemented.

    Thanks!

    Leave a comment:


  • replied
    FaSDt1517




    There's four things to keep in mind doing things this way:

    * Transitions are UFunctions, you never call them manually.
    * Your transition functions must be named as follows: "From + StateName + To + NewStateName".
    * You never call any SetState() functions, the custom component calls them when your transition function succeeds.
    * You usually do all the state work inside of your custom FSM component class, instead of in owner character class.

    Here's an example Character Class + Custom FSM Component:


    FSM_NativeCharacter_AutoFlowAPI.h:
    Code:
    #pragma once
    
    #include "UFSM.h"
    #include "GameFramework/Character.h"
    #include "FSM_NativeCharacter_AutoFlowAPI.generated.h"
    
    
    class UFSM_AutoFlowAPI;
    
    
    UCLASS()
    class UNREAL_FSM_API AFSM_NativeCharacter_AutoFlowAPI : public ACharacter
    {
        GENERATED_BODY()
    
    public:
        // Sets default values for this character's properties
        AFSM_NativeCharacter_AutoFlowAPI();
    
        UPROPERTY()
        UFSM_AutoFlowAPI* StateMachine;
    
        UPROPERTY()
        float Energy = 0.0f;
    
    protected:
    
        UFUNCTION() void OnBeginState(uint8 StateID, uint8 PreviousStateID, FName StateName, FSM_Transition Transition);
        UFUNCTION() void OnUpdateState(uint8 StateID, FName StateName, float StateTime);
        UFUNCTION() void OnExitState(uint8 StateID, FName StateName, FSM_Transition Transition);
    
    };

    FSM_NativeCharacter_AutoFlowAPI.cpp:
    Code:
    #include "FSM_NativeCharacter_AutoFlowAPI.h"
    #include "FSM_AutoFlowAPI.h"
    
    
    AFSM_NativeCharacter_AutoFlowAPI::AFSM_NativeCharacter_AutoFlowAPI()
    {
        PrimaryActorTick.bCanEverTick = true;
    
        StateMachine = CreateDefaultSubobject<UFSM_AutoFlowAPI>(TEXT("StateMachine"));
        if (StateMachine->IsValidLowLevelFast()) {
    
            StateMachine->OnBegin.AddDynamic(this,&AFSM_NativeCharacter_AutoFlowAPI::OnBeginState);
            StateMachine->OnUpdate.AddDynamic(this,&AFSM_NativeCharacter_AutoFlowAPI::OnUpdateState);
            StateMachine->OnExit.AddDynamic(this,&AFSM_NativeCharacter_AutoFlowAPI::OnExitState);
    
        }
    }
    
    
    void AFSM_NativeCharacter_AutoFlowAPI::OnBeginState(uint8 StateID, uint8 PreviousStateID, FName StateName, FSM_Transition Transition)
    {
        LOG_FSM(true,FString::Printf(TEXT("On Begin State::  %s"),*StateName.ToString()));
    }
    
    void AFSM_NativeCharacter_AutoFlowAPI::OnUpdateState(uint8 StateID, FName StateName, float StateTime)
    {
        LOG_FSM(true,FString::Printf(TEXT("On Update State::  %s"),*StateName.ToString()));
    }
    
    void AFSM_NativeCharacter_AutoFlowAPI::OnExitState(uint8 StateID, FName StateName, FSM_Transition Transition)
    {
        LOG_FSM(true,FString::Printf(TEXT("On Exit State::  %s"),*StateName.ToString()));
    }


    FSM_AutoFlowAPI.h:
    Code:
    #pragma once
    
    #include "UFSM.h"
    #include "FSM_AutoFlowAPI.generated.h"
    
    
    class AFSM_NativeCharacter_AutoFlowAPI;
    
    
    UCLASS()
    class UNREAL_FSM_API UFSM_AutoFlowAPI : public UStateMachineComponent
    {
        GENERATED_BODY()
    
    public:
        UFSM_AutoFlowAPI();
    
    
        UFUNCTION() void OnBeginIdle(const FSM_BeginEvent StateInfo);
        UFUNCTION() void OnUpdateIdle(const FSM_UpdateEvent StateInfo);
        UFUNCTION() void OnExitIdle(const FSM_ExitEvent StateInfo);
    
        UFUNCTION() void OnBeginRun(const FSM_BeginEvent StateInfo);
        UFUNCTION() void OnUpdateRun(const FSM_UpdateEvent StateInfo);
        UFUNCTION() void OnExitRun(const FSM_ExitEvent StateInfo);
    
    
        UFUNCTION() void FromIdleToRun(FSM_Transition &Condition);
        UFUNCTION() void FromRunToIdle(FSM_Transition &Condition);
    
    };

    FSM_AutoFlowAPI.cpp:
    Code:
    #include "FSM_AutoFlowAPI.h"
    #include "UFSM_FunctionLibrary.h"
    #include "Math/UnrealMathUtility.h"
    
    #include "FSM_NativeCharacter_AutoFlowAPI.h"
    
    
    UFSM_AutoFlowAPI::UFSM_AutoFlowAPI()
    {
        PrimaryComponentTick.bStartWithTickEnabled = true;
        PrimaryComponentTick.bCanEverTick = true;
        bWantsInitializeComponent = true;
        bAutoActivate = true;
    
        BlueprintAutoFlowFSM = true;
        BlueprintAutoFlowTransitions = true;
    
        AddState(0,FName("Idle"));
        AddState(1,FName("Run"));
        AddState(2,FName("Jump"));
    
        StartupState = FName("Idle");
    }
    
    
    
    void UFSM_AutoFlowAPI::OnBeginIdle(const FSM_BeginEvent StateInfo)
    {
        LOG_FSM(true,TEXT("On Begin Idle!"));
    }
    
    void UFSM_AutoFlowAPI::OnUpdateIdle(const FSM_UpdateEvent StateInfo)
    {
        LOG_FSM(true,TEXT("On Update Idle!"));
    }
    
    void UFSM_AutoFlowAPI::OnExitIdle(const FSM_ExitEvent StateInfo)
    {
        LOG_FSM(true,TEXT("On Exit Idle!"));
    }
    
    
    void UFSM_AutoFlowAPI::OnBeginRun(const FSM_BeginEvent StateInfo)
    {
        LOG_FSM(true,TEXT("On Begin Run!"));
    }
    
    void UFSM_AutoFlowAPI::OnUpdateRun(const FSM_UpdateEvent StateInfo)
    {
        LOG_FSM(true,TEXT("On Update Run!"));
    }
    
    void UFSM_AutoFlowAPI::OnExitRun(const FSM_ExitEvent StateInfo)
    {
        LOG_FSM(true,TEXT("On Exit Run!"));
    }
    
    
    void UFSM_AutoFlowAPI::FromIdleToRun(FSM_Transition &Condition)
    {
        if (AFSM_NativeCharacter_AutoFlowAPI* Owner = Cast<AFSM_NativeCharacter_AutoFlowAPI>(GetOwner())) {
            bool isIdle = FMath::IsNearlyEqual(Owner->GetVelocity().Size(),0.f,0.1f);
            bool isGrounded = Owner->CanJump();
    
            Condition = UFSMHelper::FSM_EvaluateTwoBools(isGrounded,isIdle);
        }
    }
    
    void UFSM_AutoFlowAPI::FromRunToIdle(FSM_Transition &Condition)
    {
        bool timeout = (StateTime >= 5.f);
    
        if (AFSM_NativeCharacter_AutoFlowAPI* Owner = Cast<AFSM_NativeCharacter_AutoFlowAPI>(GetOwner())) {
            bool exausted = FMath::IsNearlyEqual(Owner->Energy,0.f,0.1f);
            bool stop = (timeout && exausted);
    
            Condition = UFSMHelper::FSM_EvaluateBool(stop);
        }
    }


    Pay extra attention to state function signatures, They cannot deviate from that.
    Transition params should be always be (FSM_Transition &Condition) and state params should always be (const FSM_xxxEvent StateInfo).


    If you recreate example above and drop the FSM_NativeCharacter_AutoFlowAPI character inside a level, when playing it is going to enter "Run" state every 5 seconds then go back to "Idle" and start "Run" again... :

    Leave a comment:


  • replied
    FaSDt1517 this plugin was built to support several different workflows (depending on team's preferences)..

    For the model you intend to use, you should create of sub-class of UStateMachineComponent and attach that subclass to your Actor.
    I am going to work right now, but as soon I have some free minutes I post a C++ example for you to study.

    Leave a comment:


  • replied
    So SetState() have to be called in Tick() or OnAnyUpdateState()
    I think what I am trying to do is to define a conditional state transition which would be executed when we are in a state to know if there is a state change.

    Code:
     var fsm = new FiniteStateMachine<string>("closed", "open", "locked");
    fsm.AddTransition("closed", "open", OPEN_COMMAND)    
    .AddTransition("closed", "locked", LOCK_COMMAND, customTransition) // using a custom transition    
    .AddTransition("locked", "closed", UNLOCK_COMMAND, () => user.HasKey()) // using a condition    
    .AddTransition("open", "closed", CLOSE_COMMAND)    
    .OnEnter(open, () => Debug.Log("The door is now open!"))    
    OnExit(closed, HandleDoorIsNoLongerClosed);
    https://github.com/dubit/unity-fsm

    but I understand if it is not the way to use the ufsm plugin.
    thank you

    Leave a comment:


  • replied
    You should look in plugin classes and see how "conditional SetState()" works.

    If you want to call SetState() that way you should setup a condition to do so once the door is fully open.

    Leave a comment:

Working...
X