Expose state context members to blueprint and add Finish function to state
This commit is contained in:
parent
c652716895
commit
3938ac54b5
@ -82,7 +82,7 @@ struct FFFInputSequence
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
UCLASS( ClassGroup=(UnrealFightingFramework), meta=(BlueprintSpawnableComponent) )
|
||||||
class UNREALFIGHTINGFRAMEWORK_API UFFInputBufferComponent : public UActorComponent
|
class UNREALFIGHTINGFRAMEWORK_API UFFInputBufferComponent : public UActorComponent
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
@ -44,6 +44,17 @@ void UFFState::Exit(const FFFStateContext& InStateContext)
|
|||||||
void UFFState::Update(float OneFrame, const FFFStateContext& InStateContext)
|
void UFFState::Update(float OneFrame, const FFFStateContext& InStateContext)
|
||||||
{
|
{
|
||||||
OnUpdate(OneFrame, InStateContext);
|
OnUpdate(OneFrame, InStateContext);
|
||||||
|
|
||||||
|
if(InStateContext.Parent->GetTicksInState() >= StateDuration)
|
||||||
|
{
|
||||||
|
Finish(InStateContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UFFState::Finish(const FFFStateContext& InStateContext)
|
||||||
|
{
|
||||||
|
InStateContext.Parent->SwitchToEntryState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -84,16 +95,6 @@ bool UFFState::CanTransition_Implementation(const FFFStateContext& InStateContex
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UFFState::GotoSubState(FName InSubStateLabel)
|
|
||||||
{
|
|
||||||
UFFStateMachineComponent* SMC = Cast<UFFStateMachineComponent>(GetOuter());
|
|
||||||
if(SMC)
|
|
||||||
{
|
|
||||||
SMC->SetSubStateLabel(InSubStateLabel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
UWorld* UFFState::GetWorld() const
|
UWorld* UFFState::GetWorld() const
|
||||||
{
|
{
|
||||||
UFFStateMachineComponent* SMC = Cast<UFFStateMachineComponent>(GetOuter());
|
UFFStateMachineComponent* SMC = Cast<UFFStateMachineComponent>(GetOuter());
|
||||||
|
@ -17,21 +17,21 @@ struct FFFStateContext
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
/** Actor that owns the avatar. Typically a player controller. */
|
/** Actor that owns the avatar. Typically a player controller. */
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
AActor* Owner;
|
AActor* Owner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actor that represents the player's avatar or an object associated with the player's avatar.
|
* Actor that represents the player's avatar or an object associated with the player's avatar.
|
||||||
* This is typically a character or a weapon.
|
* This is typically a character or a weapon.
|
||||||
*/
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
AActor* Avatar;
|
AActor* Avatar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent state machine that controls this state
|
* Parent state machine that controls this state
|
||||||
*/
|
*/
|
||||||
const class UFFStateMachineComponent* Parent;
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
class UFFStateMachineComponent* Parent;
|
||||||
/** The number of ticks that have elapsed since this state was entered into */
|
|
||||||
int64 TicksInState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,8 +95,6 @@ public:
|
|||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UFF State Properties")
|
||||||
UAnimMontage* MontageToPlay;
|
UAnimMontage* MontageToPlay;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if Avatar's is in the correct stance AND
|
* Returns true if Avatar's is in the correct stance AND
|
||||||
* the state type is enabled (or the state can be hit or whiff cancelled from the current state) AND
|
* the state type is enabled (or the state can be hit or whiff cancelled from the current state) AND
|
||||||
@ -106,12 +104,6 @@ public:
|
|||||||
UFUNCTION(BlueprintNativeEvent, Category="UFF|State")
|
UFUNCTION(BlueprintNativeEvent, Category="UFF|State")
|
||||||
bool CanTransition(const FFFStateContext& InStateContext);
|
bool CanTransition(const FFFStateContext& InStateContext);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the current SubState label on the state machine that controls this
|
|
||||||
*/
|
|
||||||
UFUNCTION(BlueprintCallable, Category="UFF|State")
|
|
||||||
void GotoSubState(FName InSubStateLabel);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called whenever this state is transitioned into.
|
* Called whenever this state is transitioned into.
|
||||||
*
|
*
|
||||||
@ -135,6 +127,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void Update(float OneFrame, const FFFStateContext& InStateContext);
|
virtual void Update(float OneFrame, const FFFStateContext& InStateContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when you want to exit from this state but no eligible transitions exist to other states,
|
||||||
|
* usually due to a lack of player input.
|
||||||
|
*
|
||||||
|
* By default this will transition to the owning state machine's entry state, which is usually
|
||||||
|
* an idle state.
|
||||||
|
*
|
||||||
|
* This function will get called automatically when the ticks in this state reaches the
|
||||||
|
* threshold set by the StateDuration member, but you can call it whenever you wish to return
|
||||||
|
* to the entry state.
|
||||||
|
*
|
||||||
|
* @param InStateContext
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable)
|
||||||
|
virtual void Finish(const FFFStateContext& InStateContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blueprint hook for whenever this state is transitioned into
|
* Blueprint hook for whenever this state is transitioned into
|
||||||
*/
|
*/
|
||||||
|
@ -14,15 +14,18 @@ UFFStateMachineComponent::UFFStateMachineComponent()
|
|||||||
|
|
||||||
void UFFStateMachineComponent::Initialize()
|
void UFFStateMachineComponent::Initialize()
|
||||||
{
|
{
|
||||||
|
UFFState* EntryStateInstance = AddState(EntryState);
|
||||||
|
|
||||||
for(const TSubclassOf<UFFState>& CurrState : DefaultStates)
|
for(const TSubclassOf<UFFState>& CurrState : DefaultStates)
|
||||||
{
|
{
|
||||||
UFFState* TempState = AddState(CurrState);
|
AddState(CurrState);
|
||||||
if(!CurrentState) // first state to be created is the entry into this state machine
|
}
|
||||||
{
|
|
||||||
CurrentState = TempState;
|
// need an entry state or something went seriously wrong
|
||||||
|
check(EntryStateInstance);
|
||||||
|
|
||||||
|
CurrentState = EntryStateInstance;
|
||||||
CurrentState->Enter(GetCurrentStateContext());
|
CurrentState->Enter(GetCurrentStateContext());
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -37,11 +40,21 @@ UFFState* UFFStateMachineComponent::AddState(TSubclassOf<UFFState> StateClassToA
|
|||||||
{
|
{
|
||||||
UFFState* TempState = NewObject<UFFState>(this, StateClassToAdd);
|
UFFState* TempState = NewObject<UFFState>(this, StateClassToAdd);
|
||||||
if(TempState)
|
if(TempState)
|
||||||
|
{
|
||||||
|
if(!FindStateWithName(TempState->Name))
|
||||||
{
|
{
|
||||||
States.Add(TempState);
|
States.Add(TempState);
|
||||||
return TempState;
|
return TempState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UE_LOG(LogTemp, Error, TEXT("State with name %s already exists in state machine for %s"),
|
||||||
|
*TempState->Name.ToString(), *GetOwner()->GetFName().ToString());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UE_LOG(LogTemp, Error, TEXT("Could not create instance of state class %s"),
|
||||||
|
*StateClassToAdd.GetDefaultObject()->Name.ToString());
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +85,20 @@ void UFFStateMachineComponent::SwitchStates(UFFState* NewState)
|
|||||||
CurrentSubStateLabel = NAME_None;
|
CurrentSubStateLabel = NAME_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UFFStateMachineComponent::SwitchToEntryState()
|
||||||
|
{
|
||||||
|
// can't have an entry state if there are no states
|
||||||
|
check(States.Num() > 0);
|
||||||
|
|
||||||
|
SwitchStates(States[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64 UFFStateMachineComponent::GetTicksInState() const
|
||||||
|
{
|
||||||
|
return TicksInState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FName UFFStateMachineComponent::GetCurrentStateName() const
|
FName UFFStateMachineComponent::GetCurrentStateName() const
|
||||||
{
|
{
|
||||||
@ -81,14 +108,9 @@ FName UFFStateMachineComponent::GetCurrentStateName() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FFFStateContext UFFStateMachineComponent::GetCurrentStateContext() const
|
FName UFFStateMachineComponent::GetCurrentSubStateLabel() const
|
||||||
{
|
{
|
||||||
FFFStateContext CurrStateContext;
|
return CurrentSubStateLabel;
|
||||||
CurrStateContext.Owner = Owner;
|
|
||||||
CurrStateContext.Avatar = Avatar;
|
|
||||||
CurrStateContext.Parent = this;
|
|
||||||
CurrStateContext.TicksInState = TicksInState;
|
|
||||||
return CurrStateContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -98,28 +120,13 @@ void UFFStateMachineComponent::SetSubStateLabel(FName InSubStateLabel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UFFState* UFFStateMachineComponent::FindStateWithName(FName StateName)
|
FFFStateContext UFFStateMachineComponent::GetCurrentStateContext()
|
||||||
{
|
{
|
||||||
for (UFFState* CurrState : States)
|
FFFStateContext CurrStateContext;
|
||||||
{
|
CurrStateContext.Owner = Owner;
|
||||||
if(CurrState->Name == StateName)
|
CurrStateContext.Avatar = Avatar;
|
||||||
{
|
CurrStateContext.Parent = this;
|
||||||
return CurrState;
|
return CurrStateContext;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UE_LOG(LogTemp, Warning,
|
|
||||||
TEXT("Could not find state in state machine with name %s on %s"), *StateName.ToString(), *Owner->GetName());
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void UFFStateMachineComponent::BeginPlay()
|
|
||||||
{
|
|
||||||
Super::BeginPlay();
|
|
||||||
|
|
||||||
Initialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -158,3 +165,27 @@ void UFFStateMachineComponent::FixedTick(float OneFrame)
|
|||||||
// Debug
|
// Debug
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UFFStateMachineComponent::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UFFState* UFFStateMachineComponent::FindStateWithName(FName StateName)
|
||||||
|
{
|
||||||
|
for (UFFState* CurrState : States)
|
||||||
|
{
|
||||||
|
if(CurrState->Name == StateName)
|
||||||
|
{
|
||||||
|
return CurrState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UE_LOG(LogTemp, Warning,
|
||||||
|
TEXT("Could not find state in state machine with name %s on %s"), *StateName.ToString(), *Owner->GetName());
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
@ -18,7 +18,7 @@
|
|||||||
*
|
*
|
||||||
* This component also calls the appropriate state logic when a state is changed or the component ticks.
|
* This component also calls the appropriate state logic when a state is changed or the component ticks.
|
||||||
*/
|
*/
|
||||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
UCLASS( ClassGroup=(UnrealFightingFramework), meta=(BlueprintSpawnableComponent) )
|
||||||
class UNREALFIGHTINGFRAMEWORK_API UFFStateMachineComponent : public UActorComponent, public IFFSystemInterface
|
class UNREALFIGHTINGFRAMEWORK_API UFFStateMachineComponent : public UActorComponent, public IFFSystemInterface
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
@ -69,18 +69,30 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SwitchStates(UFFState* NewState);
|
void SwitchStates(UFFState* NewState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transitions from CurrentState to the default entry state
|
||||||
|
*/
|
||||||
|
void SwitchToEntryState();
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure)
|
||||||
|
FORCEINLINE int64 GetTicksInState() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the current state
|
* Returns the name of the current state
|
||||||
*/
|
*/
|
||||||
UFUNCTION(BlueprintPure)
|
UFUNCTION(BlueprintPure)
|
||||||
FName GetCurrentStateName() const;
|
FORCEINLINE FName GetCurrentStateName() const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure)
|
||||||
|
FORCEINLINE FName GetCurrentSubStateLabel() const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable)
|
||||||
|
FORCEINLINE void SetSubStateLabel(FName InSubStateLabel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
FFFStateContext GetCurrentStateContext() const;
|
FFFStateContext GetCurrentStateContext();
|
||||||
|
|
||||||
void SetSubStateLabel(FName InSubStateLabel);
|
|
||||||
|
|
||||||
// IFFSystemInterface interface
|
// IFFSystemInterface interface
|
||||||
virtual void FixedTick(float OneFrame) override;
|
virtual void FixedTick(float OneFrame) override;
|
||||||
@ -91,36 +103,42 @@ protected:
|
|||||||
* Actor that owns this state machine.
|
* Actor that owns this state machine.
|
||||||
* This will typically be a player controller that possesses the avatar.
|
* This will typically be a player controller that possesses the avatar.
|
||||||
*/
|
*/
|
||||||
UPROPERTY(BlueprintReadOnly)
|
UPROPERTY()
|
||||||
AActor* Owner;
|
AActor* Owner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The avatar is an actor that this state machine represents.
|
* The avatar is an actor that this state machine represents.
|
||||||
* This will typically be a pawn or character the state machine is attached to.
|
* This will typically be a pawn or character the state machine is attached to.
|
||||||
*/
|
*/
|
||||||
UPROPERTY(BlueprintReadOnly)
|
UPROPERTY()
|
||||||
AActor* Avatar;
|
AActor* Avatar;
|
||||||
|
|
||||||
/** How many ticks have elapsed since the currently active state was entered */
|
/** How many ticks have elapsed since the currently active state was entered */
|
||||||
UPROPERTY(BlueprintReadOnly, Category="UFF|State")
|
|
||||||
int64 TicksInState;
|
int64 TicksInState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* States classes to create and add to this state machine when the game starts
|
* 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<UFFState> 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")
|
UPROPERTY(EditDefaultsOnly, Category="UFF|State Machine")
|
||||||
TArray<TSubclassOf<UFFState>> DefaultStates;
|
TArray<TSubclassOf<UFFState>> DefaultStates;
|
||||||
|
|
||||||
/** Current active state for this state machine */
|
/** Current active state for this state machine */
|
||||||
UPROPERTY(BlueprintReadOnly)
|
UPROPERTY()
|
||||||
UFFState* CurrentState;
|
UFFState* CurrentState;
|
||||||
|
|
||||||
/** Current SubState label or NAME_None if there is no SubState label set for the current state*/
|
/** Current SubState label or NAME_None if there is no SubState label set for the current state*/
|
||||||
UPROPERTY(BlueprintReadOnly)
|
|
||||||
FName CurrentSubStateLabel;
|
FName CurrentSubStateLabel;
|
||||||
|
|
||||||
// States that have been added
|
// States that have been added
|
||||||
UPROPERTY(BlueprintReadOnly)
|
UPROPERTY()
|
||||||
TArray<UFFState*> States;
|
TArray<UFFState*> States;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user