【UE4】虛幻引擎運行流程


前言

  • 當前版本:4.26.2

  • 本文原創

  • 說明:有些名詞保持英文可能更容易理解

  • 目錄

    • 游戲流程總覽

    • 各個平台啟動引擎的入口函數

    • 引擎入口函數 GuardedMain()

    • EnginePreInit 引擎預初始化

    • EngineInit 引擎初始化

    • EngineLoop 引擎主循環

    • EngineExit 引擎退出


游戲流程總覽

  • 解釋啟用引擎和運行游戲的過程。

  • 此處說明兩種主要路徑:編輯器路徑、standalone 路徑。

  • 事件的一般順序為初始化引擎、創建並初始化 GameInstance、加載關卡,最后開始游戲。然而在部分被調用函數的准確排序和函數被調用的位置方面,standalone 模式和編輯器模式之間存在差異。以下流程圖展示兩個平行運行的路徑,它們在游戲開始之前匯聚。
    image


各個平台啟動引擎的入口函數

  • 代碼路徑:Engine\Source\Runtime\Launch\Private\

  • 作為入口函數,然后進入引擎的入口函數GuardedMain。如下圖所示

    image


引擎入口函數 GuardedMain()

  • 代碼路徑:Runtime/Launch/Private/Launch.cpp

  • 執行引擎四大階段的流程:EnginePreInit 、EngineInit 、EngineLoop、EngineExit 。執行流程圖如下所示

    image


EnginePreInit 引擎預初始化

實際上調用 FEngineLoop::PreInit ,再調用 PreInitPreStartupScreenPreInitPostStartupScreen ,從而實現許多初始化和核心模塊相關的事情

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();
      • 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
  • 加載 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();
  • 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 frame
  • Scene->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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM