Ue4_GamePlay中PlayerState基本使用

 UE4游戏框架中PlayerState基本使用

1.PlayerState Spawn 过程

void AController::InitPlayerState()
{
      //Playerstate 初始化
        PlayerState = World->SpawnActor<APlayerState>(PlayerStateClassToSpawn, SpawnInfo);
}

2.关卡切换(切换) Playerstate是否析构/PlayerState 生命周期?

2.1 切换关卡过程中PlayerState 销毁时机?生命周期?

注:当前关卡切换方式为无缝切换

情况一:切换前关卡与切换后关卡 PlayerControl Class 不相同时

当进行关卡切换时,如果两个关卡中的PlayerController 类不同,则重新生成PlayerController ,生成新的PlayerController 后进行PlayerState中数据拷贝,将 原playercontrol中Reset方法PlayerState部分数据重置,并将原PlayerController 中其他数据拷贝至 新PlayerControl中的PlayerState中,原PlayerState数据销毁

情况二:切换前后关卡PlayerControl Class 相同时

如切换关卡前后两个类相同时,不重新生成新PlayerController ,先进行PlayerState中数据重置,生成一个临时存储的PlayerState,调用InitPlayerState 重新生成一个当前关卡下配置类的PlayerState,并调用SeamlessTravelTo 将原PlayerState中数据拷贝至新PlayerState中,原PlayerState销毁

总结:PlayerState 切换过程中会重新生成,原PlayerState都会被Destory

void AGameMode::HandleSeamlessTravelPlayer(AController*& C)
{
    //判断前后关卡Playercontrol class 是否相同 
    if (PC && PC->GetClass() != PCClassToSpawn)
    {
        if (PC->Player != nullptr)
        {
            APlayerController* const NewPC = SpawnPlayerControllerCommon(PC->IsLocalPlayerController() ? ROLE_SimulatedProxy : ROLE_AutonomousProxy, PC->GetFocalLocation(), PC->GetControlRotation(), PCClassToSpawn);
            if (NewPC == nullptr)
            {

            }
            else
            {
                
                // 情况一:当前后playercontrol class 不相同时
                //生成一个新Playercontrol
                //SeamlessTraveFrom 传递一个playercontrol指针
                //PC(原playercontrol) Reset,拷贝数据NewPC->playerstate = PC->Playerstate
                //销毁PC(原playercontrol)
                //重新生成playercontrol(NewPc),PC = NewPC

                PC->SeamlessTravelTo(NewPC);
                //SeamlessTravelFrom
                NewPC->SeamlessTravelFrom(PC);
                SwapPlayerControllers(PC, NewPC);
                PC = NewPC;
                C = NewPC;
            }

        }
    }
    else
    {
     //情况二
//前后关卡playercontrol class 一致时,playercontrol 不进行销毁 //playercontrol->playerstate进行重置 //用OldplayerState 保存当前playerstate内容 //InitPlayerState 生成一个新playerstate //将原OldPlayerstate拷贝至 生成的 C—>PlayerState中 //OldPlayerState 销毁 C->PlayerState->Reset(); APlayerState* OldPlayerState = C->PlayerState; //this is necessary because the old GameMode may have used a different PlayerState class C->InitPlayerState(); OldPlayerState->SeamlessTravelTo(C->PlayerState); OldPlayerState->Destroy(); } void APlayerController::SeamlessTravelFrom(APlayerController* OldPC) { // copy PlayerState data if (OldPC->PlayerState) { OldPC->PlayerState->Reset(); OldPC->PlayerState->SeamlessTravelTo(PlayerState); //@fixme: need a way to replace PlayerStates that doesn't cause incorrect "player left the game"/"player entered the game" messages OldPC->PlayerState->Destroy(); OldPC->PlayerState = NULL; } } //调用顺序SeamlessTravelTo-DispatchCopyProperties-CopyProperties //重新生成的NewPlayercontrol ->playerstate = old->playerstate 过程 void APlayerState::SeamlessTravelTo(APlayerState* NewPlayerState) { DispatchCopyProperties(NewPlayerState); NewPlayerState->SetIsOnlyASpectator(IsOnlyASpectator()); } void APlayerState::DispatchCopyProperties(APlayerState* PlayerState) { CopyProperties(PlayerState); ReceiveCopyProperties(PlayerState); } void APlayerState::CopyProperties(APlayerState* PlayerState) { PlayerState->SetScore(GetScore()); PlayerState->SetPing(GetPing()); PlayerState->ExactPing = ExactPing; PlayerState->SetPlayerId(GetPlayerId()); PlayerState->SetUniqueId(GetUniqueId().GetUniqueNetId()); PlayerState->SetPlayerNameInternal(GetPlayerName()); PlayerState->SetStartTime(GetStartTime()); PlayerState->SavedNetworkAddress = SavedNetworkAddress; }

实际项目中如何使用 PlayerState?跨关卡过程中?PlayerState 数据如何保存是否保存到下一个关卡?

1.PlayerStates可以保存玩家相关数据,主要保存玩家相关信息,玩家得分/血量/护甲值/

通过重写 PlayerState中 Reset()/CopyProperties 方法 

如重写一个M_PlayerState,重写CopyProperties方法进行跨关卡数据存储
void AM_PlayerState::CopyProperties(APlayerState* PlayerState)
{
	//
	Super::CopyProperties(PlayerState);

	PlayerState->Hp = Hp;
	PlayerState->MaxHp = MaxHp;

}
//Reset 方法,可以自定义初始化数据,如部分数据需要初始化则添加至Reset中,
//需要保留数据放在CopyProperties
void APlayerState::Reset()
{
	Super::Reset();
	SetScore(0);
	ForceNetUpdate();
}

2.如何解释Pawn 下的PlayerState 指针与PlayerControl 下的PlayerState指针?

//当Control 控制Pawn时,调用PossessedBy时
//调用SetPlayerState,即Pawn /PlayerControl PlayerState为同一个
void APawn::PossessedBy(AController* NewController)
{
	SetOwner(NewController);

	AController* const OldController = Controller;

	Controller = NewController;
	ForceNetUpdate();

	if (Controller->PlayerState != nullptr)
	{
		SetPlayerState(Controller->PlayerState);
	}
} 

PlayerState各个端同步情况

 

posted on 2022-08-29 23:31  Animer  阅读(873)  评论(0编辑  收藏  举报