Start implementing state machine
This commit is contained in:
parent
d869d0105f
commit
a42e4c6667
@ -2,8 +2,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// UE includes
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
|
||||
#include "FEState.generated.h"
|
||||
|
||||
/**
|
||||
@ -19,6 +20,9 @@ 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);
|
||||
|
||||
|
@ -1,28 +1,135 @@
|
||||
// Unreal Fighting Engine by Kevin Poretti
|
||||
|
||||
// FE includes
|
||||
#include "FEState.h"
|
||||
|
||||
#include "FEStateMachineComponent.h"
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UFEStateMachineComponent::UFEStateMachineComponent()
|
||||
{
|
||||
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
||||
// off to improve performance if you don't need them.
|
||||
// Don't use Unreal's tick instead use a fixed tick
|
||||
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()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
// ...
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
// FE includes
|
||||
#include "UnrealFightingEngine/IFESystemInterface.h"
|
||||
|
||||
// UE includes
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "UnrealFightingEngine/IFESystemInterface.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) )
|
||||
class UNREALFIGHTINGENGINE_API UFEStateMachineComponent : public UActorComponent, public IIFESystemInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this component's properties
|
||||
UFEStateMachineComponent();
|
||||
|
||||
protected:
|
||||
// Called when the game starts
|
||||
virtual void BeginPlay() override;
|
||||
/**
|
||||
* Creates and adds default states and enters the first state
|
||||
*/
|
||||
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;
|
||||
// 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