Announcement

Collapse
No announcement yet.

UFSM: Finite State Machine

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

    #76
    Hello, new customer here. When I realized what this was and that you were focusing on multiplayer lately I couldn't resist.

    Where exactly do I find the demo project?

    Comment


      #77
      Originally posted by Xodroc View Post
      Hello, new customer here. When I realized what this was and that you were focusing on multiplayer lately I couldn't resist.

      Where exactly do I find the demo project?
      Hi, you can find RPC demo here:
      https://www.dropbox.com/s/q3w0plo7w0...E4.15.zip?dl=0

      * Visual Studio is needed to build the Editor DLLs *
      | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

      Comment


        #78
        Originally posted by BrUnO XaVIeR View Post
        Hi, you can find RPC demo here:
        https://www.dropbox.com/s/q3w0plo7w0...E4.15.zip?dl=0

        * Visual Studio is needed to build the Editor DLLs *
        Thanks, got it working. Seemed like it failed to build at first and then it loaded up on the next try. Ouch on how easily those physics objects become out of sync. Have you been following this thread by chance?

        Also wondering if 4.15's new "Pose Snapshot" feature could assist in partially replicating rag dolls.

        Comment


          #79
          I know how to replicated physics, but I don't see any benefits in doing it; it's just a waste of bandwidth and will never work for people with bad internet connections.
          | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

          Comment


            #80
            {1.5.3}

            I'm finally finished porting all latest additions, changes and bug fixes;
            1.5.3 is already published for the Gumroad users, Marketplace version will take few days to update as usual:

            * Fixed a bug in AnimBP that is preventing Animation's State Machines to propagate their States to the FSM Blueprint Component when OverrideFSM is checked, currently if you are not using 1.5.3 then your 'UStateMachineABP' is broken, please upgrade.
            * Ported all of latest features from UE4.15 over to UE4.14 and UE4.13 plugins.
            | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

            Comment


              #81
              Originally posted by BrUnO XaVIeR View Post
              {1.5.3}

              I'm finally finished porting all latest additions, changes and bug fixes;
              1.5.3 is already published for the Gumroad users, Marketplace version will take few days to update as usual:

              * Fixed a bug in AnimBP that is preventing Animation's State Machines to propagate their States to the FSM Blueprint Component when OverrideFSM is checked, currently if you are not using 1.5.3 then your 'UStateMachineABP' is broken, please upgrade.
              * Ported all of latest features from UE4.15 over to UE4.14 and UE4.13 plugins.
              Hi Bruno,

              this is really really good and exactly what I was looking for. I hate messy code and blueprints get messy really quick. using your plugin made my life easier. one question though: i saw your wiki and you have a download link there. it is for free but you have a version on marketplace which costs money . are those the same ?

              another question is: are you planning to implement automatic event creation for the states ? using a switch is really a bad practice as the states grow bigger and bigger. ( I am developing an rpg and the character has different animations for different weapon types)

              Comment


                #82
                Originally posted by zickig View Post
                I hate messy code and blueprints get messy really quick. using your plugin made my life easier. one question though: i saw your wiki and you have a download link there. it is for free but you have a version on marketplace which costs money . are those the same ?
                That is a demo project, there's no plugin in there since I agree to publish the tool through Marketplace environment.

                Originally posted by zickig View Post
                Another question is: are you planning to implement automatic event creation for the states ? using a switch is really a bad practice as the states grow bigger and bigger. ( I am developing an rpg and the character has different animations for different weapon types)
                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.
                | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

                Comment


                  #83
                  [MENTION=749772]zickig[/MENTION] 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 ^_^
                  I'm sending 1.5.5 to Marketplace team this next Friday, cheers!
                  | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

                  Comment


                    #84
                    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.

                    | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

                    Comment


                      #85
                      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

                      * 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:

                      Last edited by BrUnO XaVIeR; 04-12-2017, 04:15 PM.
                      | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

                      Comment


                        #86
                        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++:
                        Code:
                        OtherActor->StateMachine->GetState(uint8 Id)->OnBeginState.AddDynamic(this,&AThisClass::OnSomeStateBegin)
                        | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

                        Comment


                          #87
                          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:
                          Code:
                          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:
                          Code:
                          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);
                          
                          }
                          Last edited by BrUnO XaVIeR; 05-21-2017, 03:40 AM.
                          | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

                          Comment


                            #88
                            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.
                            Last edited by BrUnO XaVIeR; 05-10-2017, 01:38 PM.
                            | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

                            Comment


                              #89
                              Awesome! I bought it. It's great!

                              Comment


                                #90
                                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:
                                Code:
                                #pragma once
                                
                                #include "UFSM.h"
                                #include "GameFramework/Character.h"
                                #include "FSM_NativeCharacter.generated.h"
                                
                                UCLASS()
                                class MYGAMEAPI AFSM_NativeCharacter : public ACharacter, public IFSMInterface
                                {
                                	GENERATED_BODY()
                                
                                public:
                                	// 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;
                                
                                public:	
                                	// 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();
                                
                                public:
                                	/// 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:
                                Code:
                                #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.
                                | Finite State Machine | Savior | USQLite | Object-Pool | Sound-Occlusion | Property Transfer | Magic Nodes | MORE |

                                Comment

                                Working...
                                X