逻辑状态机
为了实现对目标状态的控制,以及广播改变状态后的事件,可在蓝图中继续处理不同状态下的行为。
实现过程:
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组件后,选中组件添加相关触发事件:
击中时改变目标Actor的状态:
进入相应状态改变后的行为:如击飞,击退。