[UE4] Unreal Engine running process

foreword

  • Current version: 4.26.2

  • Original article

  • Explanation: It may be easier to understand some nouns in English

  • Table of contents

    • Game flow overview

    • The entry function of each platform startup engine

    • Engine entry function GuardedMain()

    • EnginePreInit engine pre-initialization

    • EngineInit engine initialization

    • EngineLoop engine main loop

    • EngineExit engine exit


Game flow overview

  • Explains the process of enabling the engine and running the game.

  • Two main paths are illustrated here: the editor path, and the standalone path.

  • The general sequence of events is to initialize the engine, create and initialize a GameInstance, load the level, and finally start the game. However, there are differences between standalone mode and editor mode in terms of the exact ordering of partially called functions and where functions are called. The following flowchart shows two paths running in parallel, which converge before the game starts.


The entry function of each platform startup engine

  • code path:Engine\Source\Runtime\Launch\Private\

  • As an entry function, then enter the engine's entry function GuardedMain. As shown below


Engine entry function GuardedMain()

  • code path:Runtime/Launch/Private/Launch.cpp

  • Execute the four stages of the engine process: EnginePreInit, EngineInit, EngineLoop, EngineExit. The execution flow chart is as follows


EnginePreInit engine pre-initialization

actually call  FEngineLoop::PreInit , and then call  PreInitPreStartupScreen and  PreInitPostStartupScreen , so as to achieve many initialization and core module related things

Execution flow in PreInitPreStartupScreen

  • Perform various initializations first, such as parsing command parameters, trace, stat (performance analysis tool), FModuleManager, IFileManager, FPlatformFileManager, various paths, etc.

  • Load the CoreUObject module and start FTaskGraphInterface

  • via LoadPreInitModules()

    • Load Engine, Renderer, AnimGraphRuntime modules

    • Load D3D12RHI, D3D11RHI, OpenGLDrv and other modules through FPlatformApplicationMisc::LoadPreInitModules() (according to the platform)

    • Load the SlateRHIRenderer module (under non-server)

    • Load Landscape, RenderCore modules

    • Load TextureCompressor, AudioEditor, AnimationModifiers modules

  • via FEngineLoop::AppInit()

    • localized text
    • Init logging to disk
    • init config system
      • Load Engine, Game, Input configuration files through FConfigCacheIni::LoadGlobalIniFile
      • Other configuration files include: Editor, EditorPerProjectUserSettings, EditorSettings, EditorKeyBindings, EditorLayout, Lightmass, Scalability, Hardware, DeviceProfiles, GameUserSettings, etc.
    • Load "asap" plugin modules, load modules of type EarliestPossible for projects and plugins
    • Check project and plugin module data, whether compilation is required
    • Load modules of type PostConfigInit for projects and plugins
    • Initialize the headset PreInitHMDDevice();
    • print initialization log
    • Initialize other systems FCoreDelegates::OnInit.Broadcast();
  • Set the game main thread

  • Thread pool initialization (if multithreading is supported)

  • Asynchronous IO system initialization (if multithreading is supported)

  • System settings system settings and cvar initialization, cvar is obtained from the ini file, including rendering parameters, resolution, window mode, etc.

  • Scalability system initialization InitScalabilitySystem()

  • rendering thread UseRenderThread()

  • Platform-specific initialization such as  FPlatformMisc::PlatformInit() , FPlatformApplicationMisc::Init() ,FPlatformMemory::Init()

  • IPlatformFeaturesModule::Get()

  • Physics engine initialization InitGamePhys()

  • Engine localization initialization InitEngineTextLocalization()

  • Start the audio thread UseAudioThread()

  • Startup screen display FPlatformSplash::Show();

  • Platform application creation  FSlateApplication::Create(); EKeys::Initialize(), FCoreStyle::ResetToDefault() in server mode

  • RHI initialization RHIInit()

  • RenderUtils initialization RenderUtilsInit()

  • FShaderCodeLibrary::InitForRuntime()

  • FShaderPipelineCache::Initialize()

  • Shader hash cache: InitializeShaderHashCache()

  • GetRendererModule

  • InitializeShaderTypes

  • CompileGlobalShaderMap

  • CreateMoviePlayer

  • etc

Execution flow in PreInitPostStartupScreen

  • Play startup animation GetMoviePlayer()->SetupLoadingScreenFromIni()
  • Loading project modules of type PreEarlyLoadingScreen
    •  Create the window by  FPreLoadScreenManager::Get()->Initialize() calling UGameEngine::CreateGameWindow();
  • Pak file fetching and mounting
  • Config file acquisition and parameter reading
  • SlateRenderer initialization
  • Load the AssetRegistry module
  • UObject classes registration and initialization
  • PIEPreviewDeviceProfileSelector
  • InitDefaultMaterials
  • Initialize the texture streaming system
  • Load the core startup module LoadStartupCoreModules, including
    • 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
  • Load modules of type PreDefault, Default, PostDefault through LoadStartupModules
  • Load a module of type PreLoadingScreen
  • Load modules of type PostEngineInit for projects and plugins
  • Online module
  • etc

EngineInit engine initialization

execute GEngineLoop.Init() . If the editor will execute  EditorInit() , in essence,  GEngineLoop.Init() after the execution of the event, some resources of the Editor will be loaded

GEngineLoop.Init()

The analysis is mainly based on the Game non-editor mode

  • Non-editor mode: GEngine = NewObject<UEngine>(GetTransientPackage(), EngineClass);
    Editor mode:GEngine = GEditor = GUnrealEd = NewObject<UUnrealEdEngine>(GetTransientPackage(), EngineClass);
  • GEngine->Init()
    • UGameEngine::Init()  non-editor mode
      • UEngine::Init()
        • Subsystem initialization EngineSubsystemCollection.Initialize(this);
        • Head-mounted display device initialization InitializeHMDDevice();
        • Eye Tracking Device Initialization InitializeEyeTrackingDevice();
        • FSlateSoundDevice
        • load engine class LoadObject<UClass>(UEngine::StaticClass()->GetOuter()...
        • Engine. ini LoadConfig();
        • Initialize the Object reference InitializeObjectReferences();
        • for editor CreateNewWorldContext()
        • InitializeAudioDeviceManager();
        • Something related to 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();
      • Create game instance
        GameInstance = NewObject<UGameInstance>(this, GameInstanceClass);
        GameInstance->InitializeStandalone(); - CreateNewWorldContext
      • GameInstance->Init();
        • OnlineSession = NewObject<UOnlineSession>(this, SpawnClass);
          OnlineSession->RegisterOnlineDelegates();
        • SubsystemCollection.Initialize(this);
      • Initialize viewport client
  • Load a module of type PostEngineInit
  • GEngine->Start()
    • UGameEngine::Start()  non-editor mode
      • GameInstance->StartGameInstance();
      • const UGameMapsSettings* GameMapsSettings = GetDefault<UGameMapsSettings>();
      • const FString& DefaultMap = GameMapsSettings->GetGameDefaultMap();
      • Engine->Browse() server related
      • UEngine->LoadMap
        • Do some cleaning work, Unload the current world, display the loading screen, clean up the network, etc.
        • LoadPackage() , load level
        • Set 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 );
          • Some settings of the physical properties of the scene, such as gravity, collision
        • Some network related such as NetDriver, listen, etc.
        • WorldContext.World()->SetGameMode();
        • GShaderCompilingManager->ProcessAsyncResults()
        • WorldContext.World()->CreateAISystem();
        • WorldContext.World()->InitializeActorsForPlay();
        • FNavigationSystem::AddNavigationSystemToWorld()
        • SpawnPlayActor()
        • WorldContext.World()->BeginPlay();
          • GameMode->StartPlay();
            • GameState->HandleBeginPlay();
              • GetWorldSettings()->NotifyBeginPlay();
                Call BeginPlay() for each Actor, 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
  • thread heartbeat package FThreadHeartBeat::Get().Start();
  • external analyzer
  • etc

editorInit()

Executed after calling GEngineLoop.Init()

  • Some command lines, notifications, messages, logs, ui, etc. registration
  • Load the level startup map
  • Process global shader results before we try to render anything
  • InitEngineAnalytics
  • etc

EngineLoop engine main loop

Execute FEngineLoop::Tick()

  • TickRenderingTickables();
    Make sure something is ticking the rendering tickables in -onethread mode to avoid leaks/bugs.
  • ActiveProfiler->FrameSync();
    External Analyzer Frame Synchronization
  • FCoreDelegates::OnBeginFrame.Broadcast();
  • GLog->FlushThreadedLogs();
    Refresh thread log
  • FlushRenderingCommands()
    Render Command Update
  • Scene->UpdateAllPrimitiveSceneInfos()
  • BeginFrameRenderThread()
    beginning of RHI frame
  • Scene->StartFrame();
  • FlushPendingDeleteRHIResources_RenderThread();
    Some tasks in the rendering thread that require frame processing
  • Some stats related things
  • GEngine->Tick()
    main game engine tick (world, game objects, etc.)
    • log update
    • CleanupGameViewport();
    • Update subsystems
    • tick() update for FEngineAnalytics, FStudioAnalytics
    • Context.World()->Tick()
    • USkyLightComponent::UpdateSkyCaptureContents(Context.World());
      UReflectionCaptureComponent::UpdateReflectionCaptureContents(Context.World());
    • ULocalPlayer processing
    • LevelStreaming processing
    • FTickableGameObject::TickObjects()
    • MediaModule->TickPostEngine();
    • GameViewport->Tick(DeltaSeconds);
    • RedrawViewports();
      Render everything.
    • IStreamingManager、GameAudioDeviceManager 更新
    • Rendering thread commands related updates GRenderingRealtimeClock, GRenderTargetPool, FRDGBuilder, ICustomResourcePool
  • GShaderCompilingManager->ProcessAsyncResults(true, false);
  • GDistanceFieldAsyncQueue->ProcessAsyncTasks();
  • MediaModule->TickPreSlate();
    tick media framework
  • slate tick and task
  • ReplicatedProperties property synchronization
  • FTaskGraphInterface processing of some parallel tasks
  • RHITick()
  • frame count, frame interval
  • Objects next frame recovery ratio mark
  • FrameEndSync frame end synchronization event
  • EndFrameRenderThread()
  • FCoreDelegates::OnEndFrame.Broadcast();

EngineExit engine exit

  • Execution  GEngineLoop.Exit() , mainly to close and release the various modules of the engine, see the source code for details

  • last call  FEngineLoop::AppExit(); exit the application

  • source code

    
    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();
    }
    

reference

  • The original address of this article  [UE4] Unreal Engine running process - Di Cairen - Blog Park
  • Game flow overview
  • \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

Guess you like

Origin blog.csdn.net/ttod/article/details/127743405#comments_25134919