逻辑状态机

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

实现过程:

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的状态:



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



posted on 2016-03-16 15:40  Corgi  阅读(2203)  评论(0编辑  收藏  举报