Start implementing state machine
This commit is contained in:
parent
d869d0105f
commit
a42e4c6667
@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// UE includes
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "UObject/NoExportTypes.h"
|
|
||||||
#include "FEState.generated.h"
|
#include "FEState.generated.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,6 +20,9 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes pointers to what owns this state and what avatar this state represents.
|
* 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);
|
virtual void InitActorInfo(AActor* InOwner, AActor* InAvatar);
|
||||||
|
|
||||||
|
@ -1,28 +1,135 @@
|
|||||||
// Unreal Fighting Engine by Kevin Poretti
|
// Unreal Fighting Engine by Kevin Poretti
|
||||||
|
|
||||||
|
// FE includes
|
||||||
|
#include "FEState.h"
|
||||||
|
|
||||||
#include "FEStateMachineComponent.h"
|
#include "FEStateMachineComponent.h"
|
||||||
|
|
||||||
// Sets default values for this component's properties
|
|
||||||
UFEStateMachineComponent::UFEStateMachineComponent()
|
UFEStateMachineComponent::UFEStateMachineComponent()
|
||||||
{
|
{
|
||||||
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
// Don't use Unreal's tick instead use a fixed tick
|
||||||
// off to improve performance if you don't need them.
|
|
||||||
PrimaryComponentTick.bCanEverTick = false;
|
PrimaryComponentTick.bCanEverTick = false;
|
||||||
|
|
||||||
// ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Called when the game starts
|
void UFEStateMachineComponent::Initialize()
|
||||||
|
{
|
||||||
|
for(const TSubclassOf<UFEState>& CurrState : DefaultStates)
|
||||||
|
{
|
||||||
|
UFEState* TempState = AddState(CurrState);
|
||||||
|
if(!CurrentState) // first state to be created is the entry into this state machine
|
||||||
|
{
|
||||||
|
CurrentState = TempState;
|
||||||
|
CurrentState->Enter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UFEStateMachineComponent::InitActorInfo(AActor* InOwner, AActor* InAvatar)
|
||||||
|
{
|
||||||
|
Owner = InOwner;
|
||||||
|
Avatar = InAvatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UFEState* UFEStateMachineComponent::AddState(TSubclassOf<UFEState> StateClassToAdd)
|
||||||
|
{
|
||||||
|
UFEState* TempState = NewObject<UFEState>(this, StateClassToAdd);
|
||||||
|
if(TempState)
|
||||||
|
{
|
||||||
|
States.Add(TempState);
|
||||||
|
TempState->InitActorInfo(Owner, Avatar);
|
||||||
|
return TempState;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UFEStateMachineComponent::AddStates(const TArray<TSubclassOf<UFEState>>& StateClassesToAdd)
|
||||||
|
{
|
||||||
|
for(const TSubclassOf<UFEState>& CurrState : StateClassesToAdd)
|
||||||
|
{
|
||||||
|
AddState(CurrState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UFEStateMachineComponent::RemoveState(FName StateToRemove)
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Error, TEXT("UFEStateMachineComponent::RemoveState is not yet implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFEStateMachineComponent::SwitchStates(UFEState* NewState)
|
||||||
|
{
|
||||||
|
check(NewState);
|
||||||
|
|
||||||
|
CurrentState->Exit();
|
||||||
|
CurrentState = NewState;
|
||||||
|
CurrentState->Enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FName UFEStateMachineComponent::GetCurrentStateName() const
|
||||||
|
{
|
||||||
|
return CurrentState ? CurrentState->Name : NAME_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UFEState* UFEStateMachineComponent::FindStateWithName(FName StateName)
|
||||||
|
{
|
||||||
|
for (UFEState* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void UFEStateMachineComponent::BeginPlay()
|
void UFEStateMachineComponent::BeginPlay()
|
||||||
{
|
{
|
||||||
Super::BeginPlay();
|
Super::BeginPlay();
|
||||||
|
|
||||||
// ...
|
Initialize();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UFEStateMachineComponent::FixedTick(float OneFrame)
|
void UFEStateMachineComponent::FixedTick(float OneFrame)
|
||||||
{
|
{
|
||||||
|
// Should we switch states?
|
||||||
|
|
||||||
|
for(UFEState* CurrState : States)
|
||||||
|
{
|
||||||
|
// Check if the state is enabled
|
||||||
|
|
||||||
|
// Check state entry conditions if there are any
|
||||||
|
|
||||||
|
// Check input conditions if there are any
|
||||||
|
|
||||||
|
// If all state entry conditions are good and at least one input condition is good then we can transition
|
||||||
|
|
||||||
|
// Lastly just check if the state we're about to transition into isn't the current state.
|
||||||
|
// It is OK to transition if state's "CanTransitionToSelf" is true
|
||||||
|
|
||||||
|
// SwitchStates(NewState);
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentState should never be null
|
||||||
|
// TODO: Should probably assert or whatever UE's equivalent is
|
||||||
|
check(CurrentState);
|
||||||
|
|
||||||
|
// Tick current state
|
||||||
|
CurrentState->FixedTick(OneFrame);
|
||||||
|
|
||||||
|
// Debug
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,25 +2,117 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// FE includes
|
||||||
|
#include "UnrealFightingEngine/IFESystemInterface.h"
|
||||||
|
|
||||||
|
// UE includes
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "Components/ActorComponent.h"
|
#include "Components/ActorComponent.h"
|
||||||
#include "UnrealFightingEngine/IFESystemInterface.h"
|
|
||||||
#include "FEStateMachineComponent.generated.h"
|
#include "FEStateMachineComponent.generated.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A state machine is a component that evaluates and controls the transitions for state objects that
|
||||||
|
* are a part of this state machine.
|
||||||
|
*
|
||||||
|
* This component also calls the appropriate state logic when a state is changed or the component ticks.
|
||||||
|
*/
|
||||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
||||||
class UNREALFIGHTINGENGINE_API UFEStateMachineComponent : public UActorComponent, public IIFESystemInterface
|
class UNREALFIGHTINGENGINE_API UFEStateMachineComponent : public UActorComponent, public IIFESystemInterface
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Sets default values for this component's properties
|
|
||||||
UFEStateMachineComponent();
|
UFEStateMachineComponent();
|
||||||
|
|
||||||
protected:
|
/**
|
||||||
// Called when the game starts
|
* Creates and adds default states and enters the first state
|
||||||
virtual void BeginPlay() override;
|
*/
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
public:
|
/**
|
||||||
|
* Initializes pointers to what owns this state machine and what avatar this state represents.
|
||||||
|
*
|
||||||
|
* These pointers will also be passed to the states owned by this state machine.
|
||||||
|
*
|
||||||
|
* @param InOwner Actor that owns this state machine.
|
||||||
|
* @param InAvatar Actor that this state machine represents.
|
||||||
|
*/
|
||||||
|
virtual void InitActorInfo(AActor* InOwner, AActor* InAvatar);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of the state class and adds newly created state to this state machine.
|
||||||
|
*
|
||||||
|
* @param StateClassToAdd State class type to be added to this state machine
|
||||||
|
*
|
||||||
|
* @return A pointer to the state that was added or nullptr if there was an issue adding or creating the state
|
||||||
|
*/
|
||||||
|
UFEState* AddState(TSubclassOf<UFEState> 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<UFEState>>& StateClassesToAdd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the state with corresponding name and removes it from this state machine.
|
||||||
|
*/
|
||||||
|
void RemoveState(FName StateToRemove);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transitions from CurrentState to the new state passed to this function
|
||||||
|
*
|
||||||
|
* Triggers the Exit callback on the CurrentState and the Enter callback on the new state
|
||||||
|
*/
|
||||||
|
void SwitchStates(UFEState* NewState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the current state
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintPure)
|
||||||
|
FName GetCurrentStateName() const;
|
||||||
|
|
||||||
|
// IIFESystemInterface interface
|
||||||
virtual void FixedTick(float OneFrame) override;
|
virtual void FixedTick(float OneFrame) override;
|
||||||
|
// End of IIFESystemInterface interface
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Actor that owns this state machine.
|
||||||
|
* This will typically be a player controller that possesses the avatar.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
AActor* Owner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The avatar is an actor that this state machine represents.
|
||||||
|
* This will typically be a pawn or character the state machine is attached to.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
AActor* Avatar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* States classes to create and add to this state machine when the game starts
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditDefaultsOnly, Category="UFE|State Machine")
|
||||||
|
TArray<TSubclassOf<UFEState>> DefaultStates;
|
||||||
|
|
||||||
|
/** Current active state for this state machine */
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
UFEState* CurrentState;
|
||||||
|
|
||||||
|
// States that have been added
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
TArray<UFEState*> States;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state with corresponding name
|
||||||
|
*/
|
||||||
|
UFEState* FindStateWithName(FName StateName);
|
||||||
|
|
||||||
|
// UActorComponent interface
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
// End of UActorComponent interface
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user