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各个端同步情况