前言
-
當前版本:4.26.2
-
說明:有些名詞保持英文可能更容易理解
-
目錄
-
游戲流程總覽
-
各個平台啟動引擎的入口函數
-
引擎入口函數 GuardedMain()
-
EnginePreInit 引擎預初始化
-
EngineInit 引擎初始化
-
EngineLoop 引擎主循環
-
EngineExit 引擎退出
-
游戲流程總覽
-
解釋啟用引擎和運行游戲的過程。
-
此處說明兩種主要路徑:編輯器路徑、standalone 路徑。
-
事件的一般順序為初始化引擎、創建並初始化 GameInstance、加載關卡,最后開始游戲。然而在部分被調用函數的准確排序和函數被調用的位置方面,standalone 模式和編輯器模式之間存在差異。以下流程圖展示兩個平行運行的路徑,它們在游戲開始之前匯聚。
各個平台啟動引擎的入口函數
-
代碼路徑:
Engine\Source\Runtime\Launch\Private\
-
作為入口函數,然后進入引擎的入口函數GuardedMain。如下圖所示
引擎入口函數 GuardedMain()
-
代碼路徑:
Runtime/Launch/Private/Launch.cpp
-
執行引擎四大階段的流程:EnginePreInit 、EngineInit 、EngineLoop、EngineExit 。執行流程圖如下所示
EnginePreInit 引擎預初始化
實際上調用 FEngineLoop::PreInit
,再調用 PreInitPreStartupScreen
和 PreInitPostStartupScreen
,從而實現許多初始化和核心模塊相關的事情
PreInitPreStartupScreen 里的執行流程
-
先進行各種初始化,如解析command參數、trace、stat(性能分析工具)、FModuleManager、IFileManager、FPlatformFileManager、各種路徑等
-
加載CoreUObject模塊,啟動FTaskGraphInterface
-
通過LoadPreInitModules()
-
加載 Engine、Renderer、AnimGraphRuntime 模塊
-
通過 FPlatformApplicationMisc::LoadPreInitModules()加載 D3D12RHI、D3D11RHI、OpenGLDrv等模塊(根據所在平台)
-
加載 SlateRHIRenderer模塊(非服務器下)
-
加載 Landscape、RenderCore 模塊
-
加載 TextureCompressor、AudioEditor、AnimationModifiers 模塊
-
-
通過 FEngineLoop::AppInit() 進行
- 本地化文本
- Init logging to disk
- init config system
- 通過 FConfigCacheIni::LoadGlobalIniFile 加載Engine、Game、Input 配置文件
- 其他配置文件還有:Editor、EditorPerProjectUserSettings、EditorSettings、EditorKeyBindings、EditorLayout、Lightmass、Scalability、Hardware、DeviceProfiles、GameUserSettings等
- Load "asap" plugin modules,為項目和插件加載類型為 EarliestPossible 的模塊
- 檢查項目和插件模塊數據,是否需要編譯
- 為項目和插件加載類型為 PostConfigInit 的模塊
- 初始化頭顯 PreInitHMDDevice();
- 打印初始化日志
- 初始化其他系統
FCoreDelegates::OnInit.Broadcast();
-
設置游戲主線程
-
線程池初始化(如果支持多線程)
-
異步IO系統初始化(如果支持多線程)
-
系統設置system settings和 cvar 初始化,cvar從 ini 文件獲取,含渲染參數、分辨率、窗口模式等
-
Scalability系統初始化
InitScalabilitySystem()
-
渲染線程
UseRenderThread()
-
平台特定的初始化,如
FPlatformMisc::PlatformInit()
、FPlatformApplicationMisc::Init()
、FPlatformMemory::Init()
-
IPlatformFeaturesModule::Get()
-
物理引擎初始化
InitGamePhys()
-
引擎本地化初始化
InitEngineTextLocalization()
-
開啟音頻線程
UseAudioThread()
-
啟動界面顯示
FPlatformSplash::Show();
-
平台應用程序創建
FSlateApplication::Create()
;服務器模式下EKeys::Initialize()、FCoreStyle::ResetToDefault(); -
RHI 初始化
RHIInit()
-
RenderUtils初始化
RenderUtilsInit()
-
FShaderCodeLibrary::InitForRuntime()
-
FShaderPipelineCache::Initialize()
-
Shader hash cache: InitializeShaderHashCache()
-
GetRendererModule
-
InitializeShaderTypes
-
CompileGlobalShaderMap
-
CreateMoviePlayer
-
etc
PreInitPostStartupScreen 里的執行流程
- 播放啟動動畫
GetMoviePlayer()->SetupLoadingScreenFromIni()
- 加載PreEarlyLoadingScreen類型的項目模塊
- 通過
FPreLoadScreenManager::Get()->Initialize()
調用UGameEngine::CreateGameWindow();
創建窗口
- 通過
- Pak 文件獲取和掛載
- Config 文件獲取和參數讀取
- SlateRenderer 初始化
- 加載 AssetRegistry 模塊
- UObject classes 注冊和初始化
- PIEPreviewDeviceProfileSelector
- InitDefaultMaterials
- Initialize the texture streaming system
- 加載核心啟動模塊 LoadStartupCoreModules,包括
- Core、Networking、Messaging
- MRMesh、UnrealEd、EditorStyle、LandscapeEditorUtilities
- SlateCore、Slate、SlateReflector、UMG
- MessageLog、CollisionAnalyzer、FunctionalTesting
- BehaviorTreeEditor、GameplayTasksEditor、StringTableEditor、VREditor、IntroTutorials、Blutility
- Overlay、MediaAssets、ClothingSystemRuntimeNv、ClothingSystemEditor、PacketHandler、NetworkReplayStreaming
- 通過LoadStartupModules 加載PreDefault、Default、PostDefault類型的模塊
- 加載 PreLoadingScreen 類型的模塊
- 為項目和插件加載 PostEngineInit 類型的模塊
- Online模塊
- etc
EngineInit 引擎初始化
執行GEngineLoop.Init()
。如果事編輯器會執行 EditorInit()
,本質上事執行 GEngineLoop.Init()
后再進行Editor 的一些資源加載
GEngineLoop.Init()
分析主要以Game非編輯器模式為主
- 非編輯器模式:
GEngine = NewObject<UEngine>(GetTransientPackage(), EngineClass);
編輯器模式:GEngine = GEditor = GUnrealEd = NewObject<UUnrealEdEngine>(GetTransientPackage(), EngineClass);
- GEngine->Init()
- UGameEngine::Init() 非編輯器模式
UEngine::Init()
- Subsystems 初始化
EngineSubsystemCollection.Initialize(this);
- 頭顯設備初始化
InitializeHMDDevice();
- 眼動追蹤設備初始化
InitializeEyeTrackingDevice();
- FSlateSoundDevice
- 加載引擎類
LoadObject<UClass>(UEngine::StaticClass()->GetOuter()...
- Engine.ini
LoadConfig();
- 初始化 Object 引用
InitializeObjectReferences();
- 為編輯器
CreateNewWorldContext()
InitializeAudioDeviceManager();
- networking 相關的一些東西
- Initialise buffer visualization system data
GetBufferVisualizationData().Initialize();
FEngineAnalytics::Initialize();
- 加載引擎 runtime modules:ImageWriteQueue、StreamingPauseRendering、MovieScene、MovieSceneTracks、LevelSequence
- Finish asset manager loading
AssetManager->FinishInitialLoading();
RecordHMDAnalytics();
- Subsystems 初始化
GetGameUserSettings()->LoadSettings();
GetGameUserSettings()->ApplyNonResolutionSettings();
- 創建 game instance
GameInstance = NewObject<UGameInstance>(this, GameInstanceClass);
GameInstance->InitializeStandalone();
—— CreateNewWorldContext GameInstance->Init();
OnlineSession = NewObject<UOnlineSession>(this, SpawnClass);
OnlineSession->RegisterOnlineDelegates();
SubsystemCollection.Initialize(this);
- 初始化 viewport client
- UGameEngine::Init() 非編輯器模式
- 加載 PostEngineInit 類型的模塊
- GEngine->Start()
- UGameEngine::Start() 非編輯器模式
GameInstance->StartGameInstance();
const UGameMapsSettings* GameMapsSettings = GetDefault<UGameMapsSettings>();
const FString& DefaultMap = GameMapsSettings->GetGameDefaultMap();
Engine->Browse()
服務器相關UEngine->LoadMap
- 做一些清理工作,Unload 當前world、顯示loading screen、清理 networking等
LoadPackage()
,加載level- 設置new world、CurrentWorld
WorldContext.SetCurrentWorld(NewWorld);
WorldContext.World()->WorldType = WorldContext.WorldType;
WorldContext.World()->InitWorld();
InitializeSubsystems()
FWorldDelegates::OnPreWorldInitialization.Broadcast(this, IVS);
AWorldSettings* WorldSettings = GetWorldSettings();
CreatePhysicsScene(WorldSettings);
CreateAISystem();
SetupParameterCollectionInstances();
Levels.Add( PersistentLevel );
- 場景物理特性的一些設置,如重力、碰撞
- 一些網絡相關如 NetDriver、listen 等
WorldContext.World()->SetGameMode();
GShaderCompilingManager->ProcessAsyncResults()
WorldContext.World()->CreateAISystem();
WorldContext.World()->InitializeActorsForPlay();
FNavigationSystem::AddNavigationSystemToWorld()
SpawnPlayActor()
WorldContext.World()->BeginPlay();
GameMode->StartPlay();
GameState->HandleBeginPlay();
GetWorldSettings()->NotifyBeginPlay();
為每個Actor調用BeginPlay(),FActorIterator It(World); It->DispatchBeginPlay(bFromLevelLoad);
GetWorldSettings()->NotifyMatchStarted();
GetAISystem()->StartPlay();
PhysicsScene->OnWorldBeginPlay();
WorldContext.World()->bWorldWasLoadedThisTick = true;
WorldContext.OwningGameInstance->LoadComplete();
- UGameEngine::Start() 非編輯器模式
WaitForEngineLoadingScreenToFinish()
WaitForMovieToFinish()
- 加載模塊: Media、AutomationWorker、AutomationController、ProfilerClient 、SequenceRecorder、SequenceRecorderSections
- 線程心跳包
FThreadHeartBeat::Get().Start();
- 外部分析器
- etc
EditorInit()
調用GEngineLoop.Init() 后執行
- 一些命令行、通知、消息、日志、ui等注冊
- 加載關卡 startup map
- Process global shader results before we try to render anything
- InitEngineAnalytics
- etc
EngineLoop 引擎主循環
執行 FEngineLoop::Tick()
TickRenderingTickables();
Make sure something is ticking the rendering tickables in -onethread mode to avoid leaks/bugs.ActiveProfiler->FrameSync();
外部分析器幀同步FCoreDelegates::OnBeginFrame.Broadcast();
GLog->FlushThreadedLogs();
刷新線程日志FlushRenderingCommands()
渲染命令更新Scene->UpdateAllPrimitiveSceneInfos()
BeginFrameRenderThread()
beginning of RHI frameScene->StartFrame();
FlushPendingDeleteRHIResources_RenderThread();
渲染線程里一些需要幀處理的任務- 一些 stats 相關的事情
GEngine->Tick()
main game engine tick (world, game objects, etc.)- log 更新
CleanupGameViewport();
- 更新 subsystems
- FEngineAnalytics、FStudioAnalytics 的 tick() 更新
Context.World()->Tick()
USkyLightComponent::UpdateSkyCaptureContents(Context.World());
UReflectionCaptureComponent::UpdateReflectionCaptureContents(Context.World());
- ULocalPlayer 處理
- LevelStreaming 處理
FTickableGameObject::TickObjects()
MediaModule->TickPostEngine();
- GameViewport->Tick(DeltaSeconds);
- RedrawViewports();
Render everything. - IStreamingManager、GameAudioDeviceManager 更新
- 渲染線程命令相關更新 GRenderingRealtimeClock、GRenderTargetPool、FRDGBuilder、ICustomResourcePool
GShaderCompilingManager->ProcessAsyncResults(true, false);
GDistanceFieldAsyncQueue->ProcessAsyncTasks();
MediaModule->TickPreSlate();
tick media framework- slate 的 tick 和 task
- ReplicatedProperties 屬性同步
- FTaskGraphInterface 一些並行任務的處理
RHITick()
- 幀計數、幀間隔
- Objects 下一幀回收比標記
- FrameEndSync 幀結束同步事件
EndFrameRenderThread()
FCoreDelegates::OnEndFrame.Broadcast();
EngineExit 引擎退出
-
執行
GEngineLoop.Exit()
,主要是關閉和釋放引擎的各個模塊,具體可看源碼 -
最后調用
FEngineLoop::AppExit()
; 退出應用 -
源碼
void FEngineLoop::Exit() { STAT_ADD_CUSTOMMESSAGE_NAME( STAT_NamedMarker, TEXT( "EngineLoop.Exit" ) ); TRACE_BOOKMARK(TEXT("EngineLoop.Exit")); GIsRunning = 0; GLogConsole = nullptr; IInstallBundleManager::InstallBundleCompleteDelegate.RemoveAll(this); // shutdown visual logger and flush all data #if ENABLE_VISUAL_LOG FVisualLogger::Get().Shutdown(); #endif // Make sure we're not in the middle of loading something. { bool bFlushOnExit = true; if (GConfig) { FBoolConfigValueHelper FlushStreamingOnExitHelper(TEXT("/Script/Engine.StreamingSettings"), TEXT("s.FlushStreamingOnExit"), GEngineIni); bFlushOnExit = FlushStreamingOnExitHelper; } if (bFlushOnExit) { FlushAsyncLoading(); } else { CancelAsyncLoading(); } } // Block till all outstanding resource streaming requests are fulfilled. if (!IStreamingManager::HasShutdown()) { UTexture2D::CancelPendingTextureStreaming(); IStreamingManager::Get().BlockTillAllRequestsFinished(); } #if WITH_ENGINE // shut down messaging delete EngineService; EngineService = nullptr; if (SessionService.IsValid()) { SessionService->Stop(); SessionService.Reset(); } if (GDistanceFieldAsyncQueue) { GDistanceFieldAsyncQueue->Shutdown(); delete GDistanceFieldAsyncQueue; } #endif // WITH_ENGINE if ( GEngine != nullptr ) { GEngine->ReleaseAudioDeviceManager(); } if ( GEngine != nullptr ) { GEngine->PreExit(); } FAudioDeviceManager::Shutdown(); // close all windows FSlateApplication::Shutdown(); #if !UE_SERVER if ( FEngineFontServices::IsInitialized() ) { FEngineFontServices::Destroy(); } #endif #if WITH_EDITOR // These module must be shut down first because other modules may try to access them during shutdown. // Accessing these modules at shutdown causes instability since the object system will have been shut down and these modules uses uobjects internally. FModuleManager::Get().UnloadModule("AssetTools", true); #endif // WITH_EDITOR FModuleManager::Get().UnloadModule("WorldBrowser", true); FModuleManager::Get().UnloadModule("AssetRegistry", true); #if !PLATFORM_ANDROID || PLATFORM_LUMIN // AppPreExit doesn't work on Android AppPreExit(); TermGamePhys(); ParticleVertexFactoryPool_FreePool(); #else // AppPreExit() stops malloc profiler, do it here instead MALLOC_PROFILER( GMalloc->Exec(nullptr, TEXT("MPROF STOP"), *GLog); ); #endif // !ANDROID // Stop the rendering thread. StopRenderingThread(); // Disable the PSO cache FShaderPipelineCache::Shutdown(); // Close shader code map, if any FShaderCodeLibrary::Shutdown(); #if !PLATFORM_ANDROID || PLATFORM_LUMIN // UnloadModules doesn't work on Android #if WITH_ENGINE // Save the hot reload state IHotReloadInterface* HotReload = IHotReloadInterface::GetPtr(); if(HotReload != nullptr) { HotReload->SaveConfig(); } #endif // Unload all modules. Note that this doesn't actually unload the module DLLs (that happens at // process exit by the OS), but it does call ShutdownModule() on all loaded modules in the reverse // order they were loaded in, so that systems can unregister and perform general clean up. FModuleManager::Get().UnloadModulesAtShutdown(); #endif // !ANDROID IStreamingManager::Shutdown(); // Tear down the RHI. RHIExitAndStopRHIThread(); DestroyMoviePlayer(); // Move earlier? #if STATS FThreadStats::StopThread(); #endif FTaskGraphInterface::Shutdown(); FPlatformMisc::ShutdownTaggedStorage(); TRACE_CPUPROFILER_SHUTDOWN(); }
參考
- 本文原創地址 https://www.cnblogs.com/shiroe/p/15547566.html
- 游戲流程總覽
- \UE_4.26\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp
- \UE_4.26\Engine\Source\Runtime\Launch\Private\Launch.cpp
- \UE_4.26\Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp
- \UE_4.26\Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp
- \UE_4.26\Engine\Source\Runtime\Engine\Private\GameEngine.cpp
- \UE_4.26\Engine\Source\Editor\UnrealEd\Private\UnrealEdGlobals.cpp
- \UE_4.26\Engine\Source\Runtime\Engine\Private\GameEngine.cpp