Start of state system rework
This commit is contained in:
parent
85f0cbf804
commit
4cf3834b2d
@ -5,51 +5,60 @@
|
||||
// FF includes
|
||||
#include "FFStateMachineComponent.h"
|
||||
|
||||
void UFFState::InitActorInfo(AActor* InOwner, AActor* InAvatar)
|
||||
|
||||
void UFFStateBehavior::Enter(const FFFStateContext& InStateContext)
|
||||
{
|
||||
Owner = InOwner;
|
||||
Avatar = InAvatar;
|
||||
OnEnter(InStateContext);
|
||||
}
|
||||
|
||||
|
||||
void UFFState::Enter()
|
||||
void UFFStateBehavior::Exit(const FFFStateContext& InStateContext)
|
||||
{
|
||||
TicksInState = 0;
|
||||
|
||||
OnEnter();
|
||||
OnExit(InStateContext);
|
||||
}
|
||||
|
||||
|
||||
void UFFState::Exit()
|
||||
void UFFStateBehavior::Update(float OneFrame, const FFFStateContext& InStateContext)
|
||||
{
|
||||
OnExit();
|
||||
OnUpdate(OneFrame, InStateContext);
|
||||
}
|
||||
|
||||
|
||||
void UFFState::Update(float OneFrame)
|
||||
{
|
||||
TicksInState++;
|
||||
|
||||
OnUpdate(OneFrame);
|
||||
}
|
||||
|
||||
|
||||
void UFFState::OnEnter_Implementation()
|
||||
void UFFStateBehavior::OnLanded_Implementation(const FFFStateContext& InStateContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UFFState::OnExit_Implementation()
|
||||
void UFFStateBehavior::OnEnter_Implementation(const FFFStateContext& InStateContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UFFState::OnUpdate_Implementation(float OneFrame)
|
||||
void UFFStateBehavior::OnExit_Implementation(const FFFStateContext& InStateContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
UWorld* UFFState::GetWorld() const
|
||||
void UFFStateBehavior::OnUpdate_Implementation(float OneFrame, const FFFStateContext& InStateContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UFFStateBehavior::OnHit_Implementation(const FFFStateContext& InStateContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UFFStateBehavior::OnBlock_Implementation(const FFFStateContext& InStateContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void UFFStateBehavior::OnInputEvent_Implementation(const FFFStateContext& InStateContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
UWorld* UFFStateBehavior::GetWorld() const
|
||||
{
|
||||
UFFStateMachineComponent* SMC = Cast<UFFStateMachineComponent>(GetOuter());
|
||||
if(SMC)
|
||||
@ -58,4 +67,4 @@ UWorld* UFFState::GetWorld() const
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -7,26 +7,12 @@
|
||||
|
||||
#include "FFState.generated.h"
|
||||
|
||||
/**
|
||||
* A state is an object that provides rules and conditions for when a state can be transitioned into
|
||||
* and logic to run when the state is entered, exited, and active.
|
||||
*/
|
||||
UCLASS()
|
||||
class UNREALFIGHTINGFRAMEWORK_API UFFState : public UObject
|
||||
USTRUCT(BlueprintType)
|
||||
struct FFFStateData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Initializes pointers to what owns this state and what avatar this state represents.
|
||||
*
|
||||
* @param InOwner Actor that owns this state machine.
|
||||
* @param InAvatar Actor that this state machine represents.
|
||||
*/
|
||||
virtual void InitActorInfo(AActor* InOwner, AActor* InAvatar);
|
||||
|
||||
/** Name of this state */
|
||||
/** Name of this state */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="UFF|State")
|
||||
FName Name;
|
||||
|
||||
@ -38,21 +24,56 @@ public:
|
||||
UPROPERTY(EditAnywhere)
|
||||
uint8 StateType;
|
||||
|
||||
/** How many ticks have elapsed since this state was entered */
|
||||
UPROPERTY(BlueprintReadOnly, Category="UFF|State")
|
||||
int32 TicksInState;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FFFStateContext
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
/** Actor that owns the avatar. Typically a player controller. */
|
||||
AActor* Owner;
|
||||
|
||||
/**
|
||||
* Actor that represents the player's avatar or an object associated with the player's avatar.
|
||||
* This is typically a character or a weapon.
|
||||
*/
|
||||
AActor* Avatar;
|
||||
|
||||
/**
|
||||
* Data associated with this state.
|
||||
* For example this can be new movement values or data about the hitboxes if this state represents an attack.
|
||||
*/
|
||||
FFFStateData StateData;
|
||||
};
|
||||
|
||||
/**
|
||||
* A state is an object that provides rules and conditions for when a state can be transitioned into
|
||||
* and logic to run when the state is entered, exited, and active.
|
||||
*/
|
||||
UCLASS()
|
||||
class UNREALFIGHTINGFRAMEWORK_API UFFStateBehavior : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** Name of this state behavior */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="UFF|State")
|
||||
FName Name;
|
||||
|
||||
// TODO: since state's are now purely behavioral can we remove these function calls?
|
||||
// They are basically redundant with OnEnter, OnUpdate, OnExit, etc.
|
||||
/**
|
||||
* Called whenever this state is transitioned into.
|
||||
*
|
||||
* Resets TicksInState and calls appropriate Blueprint hooks
|
||||
*/
|
||||
void Enter();
|
||||
void Enter(const FFFStateContext& InStateContext);
|
||||
|
||||
/**
|
||||
* Called whenever this state is transitioned out of into a new state.
|
||||
*/
|
||||
void Exit();
|
||||
void Exit(const FFFStateContext& InStateContext);
|
||||
|
||||
/**
|
||||
* Called whenever this state is active and the game logic ticks.
|
||||
@ -61,19 +82,19 @@ public:
|
||||
*
|
||||
* @param OneFrame the time that elapses during one fixed tick
|
||||
*/
|
||||
void Update(float OneFrame);
|
||||
void Update(float OneFrame, const FFFStateContext& InStateContext);
|
||||
|
||||
/**
|
||||
* Blueprint hook that is called whenever this state is transitioned into
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
|
||||
void OnEnter();
|
||||
void OnEnter(const FFFStateContext& InStateContext);
|
||||
|
||||
/**
|
||||
* Blueprint hook that is called whenever this state is transitioned out of into a new state
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
|
||||
void OnExit();
|
||||
void OnExit(const FFFStateContext& InStateContext);
|
||||
|
||||
/**
|
||||
* Blueprint hook that is called whenever this state is active and the game logic ticks
|
||||
@ -81,25 +102,21 @@ public:
|
||||
* @param OneFrame the time that elapses during one fixed tick
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
|
||||
void OnUpdate(float OneFrame);
|
||||
void OnUpdate(float OneFrame, const FFFStateContext& InStateContext);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
|
||||
void OnLanded(const FFFStateContext& InStateContext);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
|
||||
void OnHit(const FFFStateContext& InStateContext);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
|
||||
void OnBlock(const FFFStateContext& InStateContext);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent, Category="UFF|State|Events")
|
||||
void OnInputEvent(const FFFStateContext& InStateContext);
|
||||
|
||||
// UObject interface
|
||||
virtual UWorld* GetWorld() const override;
|
||||
// End of UObject interface
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Actor that owns this state.
|
||||
* This will typically be a player controller that possesses the avatar.
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
AActor* Owner;
|
||||
|
||||
/**
|
||||
* The avatar is an actor that this state represents.
|
||||
* This will typically be a pawn or character.
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
AActor* Avatar;
|
||||
};
|
||||
|
@ -0,0 +1,6 @@
|
||||
// Unreal Fighting Framework by Kevin Poretti
|
||||
|
||||
|
||||
#include "State/FFStateContextInterface.h"
|
||||
|
||||
// Add default functionality here for any IFFStateContextInterface functions that are not pure virtual.
|
@ -0,0 +1,31 @@
|
||||
// Unreal Fighting Framework by Kevin Poretti
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Interface.h"
|
||||
|
||||
#include "FFStateContextInterface.generated.h"
|
||||
|
||||
UINTERFACE(MinimalAPI)
|
||||
class UFFStateContextInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class UNREALFIGHTINGFRAMEWORK_API IFFStateContextInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual bool CheckStateEnabled(uint8 StateType) = 0;
|
||||
|
||||
virtual bool CheckStance(uint8 Stance) = 0;
|
||||
|
||||
virtual bool CheckStateEntryConditions(const TArray<uint8>& EntryConditions) = 0;
|
||||
|
||||
virtual bool CheckInputSequences(const TArray<FFFInputSequence>& InputSequences) = 0;
|
||||
};
|
@ -14,13 +14,13 @@ UFFStateMachineComponent::UFFStateMachineComponent()
|
||||
|
||||
void UFFStateMachineComponent::Initialize()
|
||||
{
|
||||
for(const TSubclassOf<UFFState>& CurrState : DefaultStates)
|
||||
for(const TSubclassOf<UFFStateBehavior>& CurrState : DefaultStates)
|
||||
{
|
||||
UFFState* TempState = AddState(CurrState);
|
||||
UFFStateBehavior* TempState = AddState(CurrState);
|
||||
if(!CurrentState) // first state to be created is the entry into this state machine
|
||||
{
|
||||
CurrentState = TempState;
|
||||
CurrentState->Enter();
|
||||
CurrentState->Enter(GetCurrentStateContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,13 +33,12 @@ void UFFStateMachineComponent::InitActorInfo(AActor* InOwner, AActor* InAvatar)
|
||||
}
|
||||
|
||||
|
||||
UFFState* UFFStateMachineComponent::AddState(TSubclassOf<UFFState> StateClassToAdd)
|
||||
UFFStateBehavior* UFFStateMachineComponent::AddState(TSubclassOf<UFFStateBehavior> StateClassToAdd)
|
||||
{
|
||||
UFFState* TempState = NewObject<UFFState>(this, StateClassToAdd);
|
||||
UFFStateBehavior* TempState = NewObject<UFFStateBehavior>(this, StateClassToAdd);
|
||||
if(TempState)
|
||||
{
|
||||
States.Add(TempState);
|
||||
TempState->InitActorInfo(Owner, Avatar);
|
||||
return TempState;
|
||||
}
|
||||
|
||||
@ -47,9 +46,9 @@ UFFState* UFFStateMachineComponent::AddState(TSubclassOf<UFFState> StateClassToA
|
||||
}
|
||||
|
||||
|
||||
void UFFStateMachineComponent::AddStates(const TArray<TSubclassOf<UFFState>>& StateClassesToAdd)
|
||||
void UFFStateMachineComponent::AddStates(const TArray<TSubclassOf<UFFStateBehavior>>& StateClassesToAdd)
|
||||
{
|
||||
for(const TSubclassOf<UFFState>& CurrState : StateClassesToAdd)
|
||||
for(const TSubclassOf<UFFStateBehavior>& CurrState : StateClassesToAdd)
|
||||
{
|
||||
AddState(CurrState);
|
||||
}
|
||||
@ -61,13 +60,15 @@ void UFFStateMachineComponent::RemoveState(FName StateToRemove)
|
||||
UE_LOG(LogTemp, Error, TEXT("UFFStateMachineComponent::RemoveState is not yet implemented"));
|
||||
}
|
||||
|
||||
void UFFStateMachineComponent::SwitchStates(UFFState* NewState)
|
||||
void UFFStateMachineComponent::SwitchStates(UFFStateBehavior* NewState)
|
||||
{
|
||||
check(NewState);
|
||||
|
||||
CurrentState->Exit();
|
||||
|
||||
CurrentState->Exit(GetCurrentStateContext());
|
||||
CurrentState = NewState;
|
||||
CurrentState->Enter();
|
||||
CurrentState->Enter(GetCurrentStateContext());
|
||||
TicksInState = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -77,11 +78,20 @@ FName UFFStateMachineComponent::GetCurrentStateName() const
|
||||
}
|
||||
|
||||
|
||||
UFFState* UFFStateMachineComponent::FindStateWithName(FName StateName)
|
||||
FFFStateContext UFFStateMachineComponent::GetCurrentStateContext() const
|
||||
{
|
||||
for (UFFState* CurrState : States)
|
||||
FFFStateContext CurrStateContext;
|
||||
CurrStateContext.Owner = Owner;
|
||||
CurrStateContext.Avatar = Avatar;
|
||||
return CurrStateContext;
|
||||
}
|
||||
|
||||
|
||||
UFFStateBehavior* UFFStateMachineComponent::FindStateWithName(FName StateName)
|
||||
{
|
||||
for (UFFStateBehavior* CurrState : States)
|
||||
{
|
||||
if(CurrState ->Name == StateName)
|
||||
if(CurrState->Name == StateName)
|
||||
{
|
||||
return CurrState;
|
||||
}
|
||||
@ -106,7 +116,7 @@ void UFFStateMachineComponent::FixedTick(float OneFrame)
|
||||
{
|
||||
// Should we switch states?
|
||||
|
||||
for(UFFState* CurrState : States)
|
||||
for(UFFStateBehavior* CurrState : States)
|
||||
{
|
||||
// Check if the state is enabled
|
||||
|
||||
@ -128,7 +138,8 @@ void UFFStateMachineComponent::FixedTick(float OneFrame)
|
||||
check(CurrentState);
|
||||
|
||||
// Tick current state
|
||||
CurrentState->Update(OneFrame);
|
||||
TicksInState++;
|
||||
CurrentState->Update(OneFrame, GetCurrentStateContext());
|
||||
|
||||
// Debug
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ public:
|
||||
*
|
||||
* @return A pointer to the state that was added or nullptr if there was an issue adding or creating the state
|
||||
*/
|
||||
UFFState* AddState(TSubclassOf<UFFState> StateClassToAdd);
|
||||
UFFStateBehavior* AddState(TSubclassOf<UFFStateBehavior> StateClassToAdd);
|
||||
|
||||
/**
|
||||
* Creates an instance of the state classes and adds newly created states to this state machine.
|
||||
*
|
||||
* @param StateClassesToAdd Array of state class types to be added to this state machine
|
||||
*/
|
||||
void AddStates(const TArray<TSubclassOf<UFFState>>& StateClassesToAdd);
|
||||
void AddStates(const TArray<TSubclassOf<UFFStateBehavior>>& StateClassesToAdd);
|
||||
|
||||
/**
|
||||
* Destroys the state with corresponding name and removes it from this state machine.
|
||||
@ -66,7 +66,7 @@ public:
|
||||
*
|
||||
* Triggers the Exit callback on the CurrentState and the Enter callback on the new state
|
||||
*/
|
||||
void SwitchStates(UFFState* NewState);
|
||||
void SwitchStates(UFFStateBehavior* NewState);
|
||||
|
||||
/**
|
||||
* Returns the name of the current state
|
||||
@ -74,6 +74,11 @@ public:
|
||||
UFUNCTION(BlueprintPure)
|
||||
FName GetCurrentStateName() const;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
FFFStateContext GetCurrentStateContext() const;
|
||||
|
||||
// IFFSystemInterface interface
|
||||
virtual void FixedTick(float OneFrame) override;
|
||||
// End of IFFSystemInterface interface
|
||||
@ -93,24 +98,28 @@ protected:
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
AActor* Avatar;
|
||||
|
||||
/** How many ticks have elapsed since the currently active state was entered */
|
||||
UPROPERTY(BlueprintReadOnly, Category="UFF|State")
|
||||
int32 TicksInState;
|
||||
|
||||
/**
|
||||
* States classes to create and add to this state machine when the game starts
|
||||
*/
|
||||
UPROPERTY(EditDefaultsOnly, Category="UFF|State Machine")
|
||||
TArray<TSubclassOf<UFFState>> DefaultStates;
|
||||
TArray<TSubclassOf<UFFStateBehavior>> DefaultStates;
|
||||
|
||||
/** Current active state for this state machine */
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
UFFState* CurrentState;
|
||||
UFFStateBehavior* CurrentState;
|
||||
|
||||
// States that have been added
|
||||
UPROPERTY(BlueprintReadOnly)
|
||||
TArray<UFFState*> States;
|
||||
TArray<UFFStateBehavior*> States;
|
||||
|
||||
/**
|
||||
* Returns the state with corresponding name
|
||||
*/
|
||||
UFFState* FindStateWithName(FName StateName);
|
||||
UFFStateBehavior* FindStateWithName(FName StateName);
|
||||
|
||||
// UActorComponent interface
|
||||
virtual void BeginPlay() override;
|
||||
|
Loading…
Reference in New Issue
Block a user