From 8420f654e8ce7e3f24e8bbcbc08798c1515e7f4e Mon Sep 17 00:00:00 2001 From: Kevin Poretti Date: Tue, 25 Jul 2023 22:25:01 -0400 Subject: [PATCH] Debug SM, expose StateData to blueprint, make state duration optional --- .../UnrealFightingFramework/State/FFState.cpp | 2 +- .../UnrealFightingFramework/State/FFState.h | 8 +++ .../State/FFStateData.h | 7 ++- .../State/FFStateMachineComponent.cpp | 58 ++++++++++++++----- .../State/FFStateMachineComponent.h | 20 ++----- 5 files changed, 60 insertions(+), 35 deletions(-) diff --git a/Source/UnrealFightingFramework/State/FFState.cpp b/Source/UnrealFightingFramework/State/FFState.cpp index 6e8e2ad..96a3a32 100644 --- a/Source/UnrealFightingFramework/State/FFState.cpp +++ b/Source/UnrealFightingFramework/State/FFState.cpp @@ -45,7 +45,7 @@ void UFFState::Update(float OneFrame, const FFFStateContext& InStateContext) { OnUpdate(OneFrame, InStateContext); - if(InStateContext.Parent->GetTicksInState() >= StateDuration) + if(bStateHasDuration && InStateContext.Parent->GetTicksInState() >= StateDuration) { Finish(InStateContext); } diff --git a/Source/UnrealFightingFramework/State/FFState.h b/Source/UnrealFightingFramework/State/FFState.h index 78c29b8..53edfea 100644 --- a/Source/UnrealFightingFramework/State/FFState.h +++ b/Source/UnrealFightingFramework/State/FFState.h @@ -49,6 +49,14 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties") FName Name; + /** + * True if this state has some duration where it should return to the entry state + * if this state is not cancelled out of by other means. + */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties") + bool bStateHasDuration; + + // TODO: this should only be editable if bStateHasDuration is true /** * How long this state will be active before finishing if this state is not cancelled out of * by other means. diff --git a/Source/UnrealFightingFramework/State/FFStateData.h b/Source/UnrealFightingFramework/State/FFStateData.h index 6452943..d2dcbc1 100644 --- a/Source/UnrealFightingFramework/State/FFStateData.h +++ b/Source/UnrealFightingFramework/State/FFStateData.h @@ -14,12 +14,15 @@ /** * */ -UCLASS() +UCLASS(BlueprintType) class UNREALFIGHTINGFRAMEWORK_API UFFStateData : public UDataAsset { GENERATED_BODY() public: + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + TSubclassOf EntryState; + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) - TArray> States; + TArray> OtherStates; }; diff --git a/Source/UnrealFightingFramework/State/FFStateMachineComponent.cpp b/Source/UnrealFightingFramework/State/FFStateMachineComponent.cpp index 2deab97..ab225f8 100644 --- a/Source/UnrealFightingFramework/State/FFStateMachineComponent.cpp +++ b/Source/UnrealFightingFramework/State/FFStateMachineComponent.cpp @@ -5,18 +5,30 @@ // FF includes #include "FFState.h" +#if !UE_BUILD_SHIPPING +static int32 StateMachineDebug = 0; +FAutoConsoleVariableRef CVARStateMachineDebug(TEXT("ff.StateMachine.ShowDebug"), + StateMachineDebug, + TEXT("Print state machine information for character"), + ECVF_Cheat); +#endif + UFFStateMachineComponent::UFFStateMachineComponent() { // Don't use Unreal's tick instead use a fixed tick - PrimaryComponentTick.bCanEverTick = false; +#if !UE_BUILD_SHIPPING + PrimaryComponentTick.bCanEverTick = true; +#else + PrimaryComponentTick.bCanEverTick = false; +#endif } -void UFFStateMachineComponent::Initialize() +void UFFStateMachineComponent::Initialize(TSubclassOf EntryState, const TArray>& InitialStates) { UFFState* EntryStateInstance = AddState(EntryState); - for(const TSubclassOf& CurrState : DefaultStates) + for(const TSubclassOf& CurrState : InitialStates) { AddState(CurrState); } @@ -134,7 +146,12 @@ void UFFStateMachineComponent::FixedTick(float OneFrame) { // CurrentState should never be null // TODO: Should probably assert or whatever UE's equivalent is - check(CurrentState); + //check(CurrentState); + // TODO: yet another reason I want FULL CONTROL over when my game objects are created and initialized + if(!CurrentState) + { + return; + } // Should we switch states? UFFState* StateToTransitionTo = nullptr; @@ -161,16 +178,6 @@ void UFFStateMachineComponent::FixedTick(float OneFrame) TicksInState++; CurrentState->Update(OneFrame, GetCurrentStateContext()); } - - // Debug -} - - -void UFFStateMachineComponent::BeginPlay() -{ - Super::BeginPlay(); - - Initialize(); } @@ -185,7 +192,26 @@ UFFState* UFFStateMachineComponent::FindStateWithName(FName StateName) } UE_LOG(LogTemp, Warning, - TEXT("Could not find state in state machine with name %s on %s"), *StateName.ToString(), *Owner->GetName()); + TEXT("Could not find state in state machine with name %s"), *StateName.ToString()); return nullptr; -} \ No newline at end of file +} + +#if !UE_BUILD_SHIPPING +void UFFStateMachineComponent::TickComponent(float DeltaTime, ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // Debug + if(StateMachineDebug) + { + FString SMDebugString = "---State Machine Info---\n"; + SMDebugString.Append(FString::Printf(TEXT("Current State: %s\n"), *CurrentState->Name.ToString())); + SMDebugString.Append(FString::Printf(TEXT("Current SubState Label: %s\n"), *CurrentSubStateLabel.ToString())); + SMDebugString.Append(FString::Printf(TEXT("Ticks In State: %lld\n"), TicksInState)); + + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Green, SMDebugString); + } +} +#endif diff --git a/Source/UnrealFightingFramework/State/FFStateMachineComponent.h b/Source/UnrealFightingFramework/State/FFStateMachineComponent.h index 4b553a3..0c8f6fa 100644 --- a/Source/UnrealFightingFramework/State/FFStateMachineComponent.h +++ b/Source/UnrealFightingFramework/State/FFStateMachineComponent.h @@ -29,7 +29,7 @@ public: /** * Creates and adds default states and enters the first state */ - void Initialize(); + void Initialize(TSubclassOf EntryState, const TArray>& InitialStates); /** * Initializes pointers to what owns this state machine and what avatar this state represents. @@ -116,20 +116,6 @@ protected: /** How many ticks have elapsed since the currently active state was entered */ int64 TicksInState; - /** - * The state the state machine will enter when the game begins and the state that will be - * transitioned into if a state finishes and no other states are eligible for transition. - */ - UPROPERTY(EditDefaultsOnly, Category="UFF|State Machine") - TSubclassOf EntryState; - - /** - * States classes other than the entry state to create and add to this state machine when the - * game starts. - */ - UPROPERTY(EditDefaultsOnly, Category="UFF|State Machine") - TArray> DefaultStates; - /** Current active state for this state machine */ UPROPERTY() UFFState* CurrentState; @@ -146,7 +132,9 @@ protected: */ UFFState* FindStateWithName(FName StateName); +#if !UE_BUILD_SHIPPING // UActorComponent interface - virtual void BeginPlay() override; + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; // End of UActorComponent interface +#endif };