三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

UE引擎初始化流程

UE引擎初始化流程

UE引擎初始化流程:从Main到BeginPlay

前言

文章只作为学习用,有错各位大佬可以指出来,不探讨设计理念,只为了看清楚UE初始化的过程,为以后理解游戏中类的载入时机和Bug调试打基础。文章不仅取自于视频,还借助过Ai,所以对其中细节的函数作用并不确定,但我不打算现在就深入到细节里去,之后有需要才去深入细节,所以这篇文章只供我自己学习复习,不断修改。

参考视频:https://www.bilibili.com/video/BV1NA411L7x4/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=d0bb3eb630952bd6c4013630f19fc966

总流程大致可以看做:

GuardedMain

FEngineLoop::PreInit(加载模块)

FEngineLoop::Init()

Tick 循环

Exit

2.各入口和其作用

GuardedMain(\Engine\Source\Runtime\Launch\Private\Lunch.cpp

进程的真正入口,包一层异常/崩溃处理,内部创建 FEngineLoop 并驱动 PreInit/Init/Tick/Exit

/*** Static guarded main function. Rolled into own function so we can have error handling for debug/ release builds depending* on whether a debugger is attached or not.*/
int32 GuardedMain( const TCHAR* CmdLine )

2.1 初始化

2.1.1 FEngineLoop::PreInit

FEngineLoop::PreInit:初始化之前还要加载模块。(大部分的模块包括插件模块都会在此时加载)

模块的加载的大致顺序后面我再说。

作用:加载引擎大部分模块、按 LoadingPhase 加载项目/插件

2.1.2 Init

1.内部发生的事情,首先就是

查找配置文件以什么方向创建了一个GEngine的对象实例,比如UEngine的子类有UEditorEngineUGameEngine。其后对其进行了初始化。

运行方式有两种:

​ 1.以游戏编辑器方式运行,就是我们在UE编辑器运行游戏所呈现的样子

​ 2.以游戏打包后的.exe方式运行

2.接下来会加载在PostEngineInit设置在Init时加载模块的项目模块

3.引擎启动

UEngine类:

  1. init()在底层模块(渲染、物理、音频等)就绪后执行,主要做:

    1. 创建 GameInstance
      按项目配置(如 GameInstanceClass)创建 UGameInstance,作为项目级逻辑的入口(存档、联机会话、全局状态等)。
    2. 创建 GameViewportClient
      连接游戏窗口与渲染管线,处理输入、分辨率、全屏等视口相关逻辑。
    3. 创建 LocalPlayer
      本地玩家控制器,关联 PlayerController、输入映射等。
    4. 初始化 Standalone 模式
      调用 UGameInstance::InitializeStandalone(),在其中创建第一个 UWorld

    从 UE 4.4 起,很多原本写在 UGameEngine 里的项目逻辑被拆到 UGameInstance 和各类 Subsystem,引擎类更偏「基础设施调度」。

  2. Start

    1. Start() 会调用 UGameInstance::StartGameInstance(),进而:

      • 读取默认地图(如 /Game/Maps/MainMenu
      • 调用 UEngine::LoadMap() / Browse() 加载关卡
      • 触发 World 初始化、Actor 生成、BeginPlay

      加载地图是 UEngine(含 UGameEngine)的核心能力之一,包括:

      • Browse():切换到新 URL/地图

      • LoadMap():异步/同步加载关卡资源(这其中也很复杂,包括创建GameModeBase,对组件初始化等)

        • LoadMap 的参数本质是 FURL,描述要加载的目标:MapName?Game=MyGameMode?Listen?Name=Player1│        │                │         │地图包名  指定 GameMode    监听端口   玩家名
          常见字段:Map:如 /Game/Maps/Dungeon(不带 .umap)
          Game:覆盖默认 GameMode 类
          Option:自定义参数字符串,可在 InitGame() 里读
          Browse 会先解析、校验 URL,再交给 LoadMap。
          
        • 通知与清理

          • 广播 FCoreDelegates::PreLoadMap 等(UI loading 屏常挂在这里)
          • 断开/清理旧 UWorld:销毁 Actor、释放 Level、清 NetDriver 绑定等
          • 非 Seamless 时:旧图所有 Actor 都会销毁(除非之前做了 Seamless 持久化标记)

          加载地图资源

          • 通过 FSoftObjectPath / 包名加载 .umap 对应 Package
          • 同步或异步(取决于调用路径和配置)
          • 可显示 Loading Movie(bStartedLoadMapMovie 就是干这个的)

          建立新 UWorld

          • 从加载的 Level 得到 UWorld
          • 写入 FWorldContext(当前上下文)
          • 设置全局 GWorld(注意:多 World / PIE 时 Context 更重要)
          • UGameInstance 关联到新 World

          初始化关卡与 GameMode

          • 初始化 Persistent Level 里的 Actor(Editor 下可能重跑 Construction Script)
          • Spawn AGameMode(只在 Server / Standalone 存在)
          • 调用 AGameMode::InitGame(),解析 URL 里的 Option
          • UWorld::InitializeActorsForPlay():注册组件、准备运行

          BeginPlay 与玩家

          • 对新 World 里符合条件的 Actor 调用 BeginPlay
          • 为每个 ULocalPlayer 临时 Spawn APlayerController(联机客户端之后可能被服务器下发的替换)

          到这里,新地图才算「可玩」

      • 管理 FWorldContext(当前 World、PIE 实例等上下文)

2.2 Tick()

编辑器或游戏跑起来后,引擎会不停循环。

步骤 内容
处理输入 键盘、鼠标
更新世界 UWorld::Tick、Actor、Component
物理 Chaos / PhysX
动画 AnimInstance
渲染 提交画面
音频 更新声音
← 返回列表