Lyra框架02:角色是怎么創(chuàng)建出來(lái)的
Lyra的創(chuàng)建角色是圍繞PawnData這個(gè)數(shù)據(jù)結(jié)構(gòu),和OnExperienceLoaded這個(gè)時(shí)間節(jié)點(diǎn)。
首先推薦一個(gè)文章先看明白GameMode的初始化流程。
https://zhuanlan.zhihu.com/p/70045930
按時(shí)間順序排列:
在UEngine::LoadMap中,首先調(diào)用UWorld::InitializeActorsForPlay初始化所有在場(chǎng)景里已經(jīng)存在的Actor。

在這個(gè)函數(shù)內(nèi),AGameModeBase::PreInitializeComponents階段,GameState被初始化的同時(shí)也將ALyraGameMode::OnExperienceLoaded注冊(cè)到了委托上。
其他放在場(chǎng)景里的Character或是Pawn,在APawn::PostInitializeComponents階段,根據(jù)AutoPossessAI的設(shè)定,開(kāi)始創(chuàng)建AIController。
而ALyraPlayerBotController中使用了bWantsPlayerState = true,因此也會(huì)獲得一個(gè)LyraPlayerState,從而在ALyraPlayerState::PostInitializeComponents階段,ALyraPlayerState::OnExperienceLoaded也注冊(cè)到了委托上。
在后續(xù)的階段,當(dāng)PlayerController被創(chuàng)建時(shí),隨著LyraPlayerState被實(shí)例化,在ALyraPlayerState::PostInitializeComponents階段,ALyraPlayerState::OnExperienceLoaded也注冊(cè)到了委托上。
當(dāng)Actors都準(zhǔn)備好了時(shí),我們開(kāi)始關(guān)注ExperienceLoaded之后的執(zhí)行邏輯。
在ALyraGameMode::InitGame中,通過(guò)SetTimerForNextTick,保證下一幀才開(kāi)始真正跑Experience的邏輯。
在ALyraGameMode::OnExperienceLoaded中,嘗試通過(guò)AGameModeBase::RestartPlayerAtPlayerStart重置所有PlayerController。
在這個(gè)過(guò)程中需要查詢(xún)PawnData數(shù)據(jù),ALyraGameMode::GetPawnDataForController函數(shù)中寫(xiě)了從LyraPlayerState上取的邏輯。這個(gè)PawnData是哪來(lái)的呢?一看原來(lái)是ALyraPlayerState::OnExperienceLoaded里,從GameMode上再調(diào)GetPawnDataForController取。
還是在這個(gè)過(guò)程中,在?ALyraGameMode::SpawnDefaultPawnAtTransform_Implementation的實(shí)現(xiàn)里,又取了一次PawnData直接生成了Pawn,然后還調(diào)用了上面的ULyraPawnExtensionComponent::SetPawnData。
目前只有HeroComponent和PawnExtensionComponent用到了這個(gè)IGameFrameworkInitStateInterface。這個(gè)模塊是用來(lái)管理BeginPlay里的邏輯時(shí)序的。
PawnExtensionComponent通過(guò)PawnData卡住所有其他用到這個(gè)模塊的Component,來(lái)保證數(shù)據(jù)可用性。

我們重新捋一下時(shí)序。
1. LyraGameMode最先注冊(cè),也最先執(zhí)行OnExperienceLoaded回調(diào)函數(shù),此時(shí)PlayerState的OnExperienceLoaded還沒(méi)有回調(diào),因此取不到PlayerState上的PawnData,所以取ExperienceManager上的默認(rèn)Experience實(shí)例。

2. LyraPlayerState執(zhí)行OnExperienceLoaded回調(diào)函數(shù),此時(shí)同上,還是取到了默認(rèn)Experience實(shí)例。然后記錄下來(lái)。后續(xù)其他地方如果要取就從PlayerState上取,應(yīng)該是因?yàn)镚ameMode只在服務(wù)器上有,客戶(hù)端取不到。
3. HeroComponent和PawnExtensionComponent在BeginPlay階段,交替切換階段,最終完成基于PawnData的輸入、能力初始化。
注:SpawnActor的流程:
https://zhuanlan.zhihu.com/p/411549290