[UE4]逻辑状态机组件

时间:2023-03-08 17:25:14

逻辑状态机

为了实现对目标状态的控制,以及广播改变状态后的事件,可在蓝图中继续处理不同状态下的行为。

实现过程:

1.继承ActorComponent实现LogicStateMachine;

2.被击中时触发设置状态;

3.状态进入/退出时触发事件。

主要代码

LogicStateMachine.h

/*
*author : Jia Zhipeng
*class : LogicStateMachine
*/
//use enum metadata to save priority
UENUM(BlueprintType)
enum LogicStateEnum
{
LS_Default = 0 UMETA(DisplayName = "Default", Priority = 1),
LS_Frozen UMETA(DisplayName = "Frozen", Priority = 1),
LS_Fly UMETA(DisplayName = "Fly", Priority = 1),
LS_OnGround UMETA(DisplayName = "OnGround", Priority = 1),
LS_Faint UMETA(DisplayName = "Faint", Priority = 1),
LS_Back UMETA(DisplayName = "Back", Priority = 1),
LogicStateNum UMETA(Hidden),
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FChangeStateSignature, LogicStateEnum, LogicState);
UCLASS(ClassGroup = LogicState, meta = (BlueprintSpawnableComponent), ShowCategories = (LogicState))
class CLIENT_API ULogicStateMachine : public UActorComponent
{
GENERATED_UCLASS_BODY()
public:
//After during time, state will be reset to default.
UFUNCTION(BlueprintCallable, Category = LogicStateMachine)
bool SetState(LogicStateEnum NewState, float DuringTime=1.0f);
//Event used in BP
UPROPERTY(BlueprintAssignable, Category = LogicStateMachine)
FChangeStateSignature OnEnterLogicState;
UPROPERTY(BlueprintAssignable, Category = LogicStateMachine)
FChangeStateSignature OnRefreshLogicState;
UPROPERTY(BlueprintAssignable, Category = LogicStateMachine)
FChangeStateSignature OnExitLogicState; virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override; virtual void OnRegister() override;
float GetElapsedTime() { return ElapsedTime; }
void SetElapsedTime(float Time) { ElapsedTime = Time; }
private:
LogicStateEnum CurrentState;
//On currentState time
float ElapsedTime;
//after this time, it will be reset to Default
float ResetToDefaultTime;
};

LogicStateMachine.cpp

/*
*author : Jia Zhipeng
*class : LogicStateMachine
*/
//主要改变状态代码
bool ULogicStateMachine::SetState(LogicStateEnum NewState, float DuringTime)
{
int NewStatePriority = 0;
int CurrentStatePriority = 0;
const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("LogicStateEnum"), true);
FString str = EnumPtr->GetMetaData(TEXT("Priority"), CurrentState);
if (!str.IsEmpty())
CurrentStatePriority = FCString::Atoi(*str);
str = EnumPtr->GetMetaData(TEXT("Priority"), NewState);
if (!str.IsEmpty())
NewStatePriority = FCString::Atoi(*str);
//根据优先级判断是否改变/刷新状态
if ( (NewState != LogicStateEnum::LS_Default) && (NewStatePriority<CurrentStatePriority))
return false;
//Time record
ElapsedTime = 0;
ResetToDefaultTime = DuringTime;
//状态相同则刷新,不同则退出旧状态,进入新状态
if (NewState == CurrentState)
OnRefreshLogicState.Broadcast(CurrentState);
if (NewState != CurrentState)
{
OnExitLogicState.Broadcast(CurrentState);
}
CurrentState = NewState;
OnEnterLogicState.Broadcast(CurrentState);
return true;
}

蓝图使用

添加LogicStateMachine组件后,选中组件添加相关触发事件:

[UE4]逻辑状态机组件

击中时改变目标Actor的状态:

[UE4]逻辑状态机组件

进入相应状态改变后的行为:如击飞,击退。

[UE4]逻辑状态机组件