UE4 源码阅读:从引擎启动到Receive Begin Play

Posted 努力成长的tory

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4 源码阅读:从引擎启动到Receive Begin Play相关的知识,希望对你有一定的参考价值。

一、引擎主循环

UE版本:4.27
一、引擎主循环的位置:
Launch.cpp : Guarded Main函数

二、、Guarded Main函数执行逻辑:
1、EnginePreInit:加载大多数模块

int32 ErrorLevel = EnginePreInit( CmdLine );

PreInit模块加载顺序:

模块加载过程:
(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)
(2)调用模块的StartUpModule方法

2、FEngineLoop::Init()
1、 检查Engine的配置文件找出使用了哪一个GameEngine类(UGameEngine和UEditorEngine,均派生自UEngine)

2、 创建该类的实例,并让全局UEngine指针(GEngine)指向该实例

(3)触发全局委托告知引擎已初始化

(4)加载插件和项目模块
(5)引擎启动成功

3、UGameEngine:
调用顺序:

(1)UGameEngine::Init:
会在地图加载完之前进行初始化,初始化过程会创建
GameInstance、GameViewportClient、LocalPlayer对象,之后游戏启动
创建GameInstance:

创建GameViewportClient,代表屏幕本身:

创建LocalPlayer,代表坐在屏幕前的用户,之后游戏启动:

(2)LoadMap的作用:
加载在DefaultEngine.ini中定义的地图,将会创建UWorld对象(保存游戏地图中所有的AActor)、以及一些在游戏地图加载后才生成的对象
上:在游戏地图加载前生成的对象
下:在游戏地图加载后生成的对象
当切换新地图中,地图中的所有对象都会被销毁,UWorld对象被清空(不使用seamless travel)

(3)LoadMap加载World的过程(UEngine::LoadMap):
1、触发全局委托表明游戏地图更换,如果当前已经加载一张地图,会清理并销毁当前World

2、GameInstance加载World

3、加载WorldPackage,创建UWorld对象,

4、在World中保存对GameInstance的引用,World对象的引用保存在WorldContext中,并将其世界类型设置为Game。
AddToRoot:防止被垃圾回收;
InitWorld:让World对象能够对一些物理,寻路,AI和声音的系统进行设置;
SetGameMode:World对象会让GameInstance在世界生成一个GameMode的Actor对象,同时所有引用到的资产都会被加载:

5、InitializeActorsForPlay:
(1)首先会注册世界中的所有Actor组件(Actor上的每一个Component也要被注册);Component注册过程(UActorComponent::RegisterComponentWithWorld)。

(2)Component被注册后,World会调用GameMode的InitGame方法,GameMode会生成一个GameSession类的Actor对象:

(3)RouteActorInitialize:
World遍历每一个Level初始化所有Actor对象,每个Actor会先调用PerInitializeComponent方法,做初始化的早期工作;GameMode作为Actor也会在这是被调用,并生成GameState对象,并将其关联到World对象中。;

之后还会对所有Actor进行一个遍历,这次会调用InitializeComponents和PostInitializeComponents方法,完成World的初始化。
6、Spawn Actor
遍历GameInstance里的所有Local Player

7、处理登录过程
8、LoadMap总结
Engine -> World World -> GameMode -> GameState

(4)游戏循环:

UE4源码Build上传Perforce

UE4每次升级个版本总是要提交大量文件到Perforce, 是件很麻烦的事. 我们的引擎编译好了会连同Binaries一起上传, 美术和策划都可以直接使用跟程序一样的版本. 这样的话, Perforce上的引擎就需要有这些注意事项:

  • 引擎目录完全包含所有代码和引擎依赖资源
  • 引擎编译输出的dll, exe等也都需要提交, 保证策划和美术能够直接拉取引擎版本
  • 引擎编译过程中会写入的文件, 需要改成writable, 不然程序开发时编译会出错
  • 需要避免上传不必要的文件, 如Intermediate目录, exp, obj等
  • [可选]如果需要定位美术和策划的引擎崩溃, 也需要上传pdb文件

如果使用P4V GUI客户端来进行这些操作, 在有大量文件的情况下, 会经常性卡死, 再说靠人力一个个去用鼠标去筛选所有附合要求的文件是件很烦人且容易出错的操作.
在这里就记录一下整个过程, 免得下次升级时又要重新找命令规则步骤之类的:

  1. 从github拉取UE4的release版本
  2. 拷贝整个目录到Perforce Workspace, 需要避免.git文件夹也拷过来
  3. 执行Setup.bat下载引擎依赖资源
  4. 上传干净的引擎目录到Perforce
  5. 因为有些编译过程中的exe和dll等在上传后变成了只读属性, 需要改成writable的:
p4 edit -t binary+w .\\Engine\\Binaries\\...\\*.dll
p4 edit -t xbinary+w .\\Engine\\Binaries\\...\\*.exe
p4 edit -t text+w .\\Engine\\Binaries\\...\\*.config
  1. 生成sln进行编译, 这个过程中会在Binaries和Plugins下面生成exe和dll等文件
  2. 由于Binaries和Plugins下面是有子目录的, 所以我们需要递归提交这些文件, 并加上writable标记
for /f "delims=" %a in ('dir .\\Engine\\Binaries\\*.dll /b /s') do p4 add -t +w %a
for /f "delims=" %a in ('dir .\\Engine\\Binaries\\*.exe /b /s') do p4 add -t +w %a
for /f "delims=" %a in ('dir .\\Engine\\Binaries\\*.target /b /s') do p4 add -t +w %a
for /f "delims=" %a in ('dir .\\Engine\\Binaries\\*.modules /b /s') do p4 add -t +w %a
for /f "delims=" %a in ('dir .\\Engine\\Plugins\\*.dll /b /s') do p4 add -t +w %a
for /f "delims=" %a in ('dir .\\Engine\\Plugins\\*.modules /b /s') do p4 add -t +w %a

因为p4 add命令是不支持路径中的”…”的, 所以需要借助dir命令递归遍历子目录下的文件, 再使用for循环针对每个文件执行add操作. 如果要把这些命令写到批处理文件里, 注意需要把%a改成%%a.

  1. 最后, 再提交一次, 完成

以上是关于UE4 源码阅读:从引擎启动到Receive Begin Play的主要内容,如果未能解决你的问题,请参考以下文章

Unity与UE4引擎源码内使用到的第三方库的比较

UE4源码Build上传Perforce

UE4引擎无法启动,

《Inside UE4》目录

UE4,UE5虚幻引擎源码版下载

编译版本引擎和发布版本引擎一个小的区别