[[C++API/Launch.cpp]]
游戏循环:死循环,Launch.cpp
```cpp
// Copyright Epic Games, Inc. All Rights Reserved.
#include "CoreMinimal.h"
#include "Misc/CommandLine.h"
#include "Misc/App.h"
#include "Misc/OutputDeviceError.h"
#include "LaunchEngineLoop.h"
#include "PhysicsPublic.h"
#include "HAL/ExceptionHandling.h"
#include "Modules/ModuleManager.h"
#include "ProfilingDebugging/LoadTimeTracker.h"
#include "Stats/StatsMisc.h"
#include "Misc/CoreDelegates.h"
#include "Misc/EngineVersion.h"
#include "Misc/ScopedSlowTask.h"
#if WITH_EDITOR
#include "UnrealEdGlobals.h"
#endif
#if PLATFORM_WINDOWS
#include "Windows/WindowsHWrapper.h"
#endif
IMPLEMENT_MODULE(FDefaultModuleImpl, Launch);
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_UNIX || PLATFORM_USE_GENERIC_LAUNCH_IMPLEMENTATION
//引擎循环
FEngineLoop GEngineLoop;
//控制台窗口
bool GIsConsoleExecutable = false;
extern "C" int test_main(int argc, char ** argp)
{
return 0;
}
/**
* PreInits the engine loop
* 引擎预加载
*/
int32 EnginePreInit( const TCHAR* CmdLine )
{
int32 ErrorLevel = GEngineLoop.PreInit( CmdLine );
return( ErrorLevel );
}
/**
* Inits the engine loop
* 初始化
*/
int32 EngineInit()
{
int32 ErrorLevel = GEngineLoop.Init();
return( ErrorLevel );
}
/**
* Ticks the engine loop
* 引擎执行每一帧的循环逻辑
*/
void EngineTick( void )
{
GEngineLoop.Tick();
}
/**
* Shuts down the engine
* 引擎退出
* */
void EngineExit( void )
{
// Make sure this is set
RequestEngineExit(TEXT("EngineExit() was called"));
GEngineLoop.Exit();
}
/**
* Performs any required cleanup in the case of a fatal error. */void LaunchStaticShutdownAfterError()
{
// Make sure physics is correctly torn down.
TermGamePhys();
}
#if WITH_EDITOR
extern UNREALED_API FSecondsCounterData BlueprintCompileAndLoadTimerData;
#endif
/**
* 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 )
{
#if !(UE_BUILD_SHIPPING)
if (FParse::Param(CmdLine, TEXT("waitforattach")))
{ while (!FPlatformMisc::IsDebuggerPresent());
UE_DEBUG_BREAK();
}#endif
BootTimingPoint("DefaultMain");
// Super early init code. DO NOT MOVE THIS ANYWHERE ELSE!
FCoreDelegates::GetPreMainInitDelegate().Broadcast();
// make sure GEngineLoop::Exit() is always called.
struct EngineLoopCleanupGuard
{
~EngineLoopCleanupGuard()
{ EngineExit();
} } CleanupGuard;
// Set up minidump filename. We cannot do this directly inside main as we use an FString that requires
// destruction and main uses SEH.
// These names will be updated as soon as the Filemanager is set up so we can write to the log file. // That will also use the user folder for installed builds so we don't write into program files or whatever.#if PLATFORM_WINDOWS
FCString::Strcpy(MiniDumpFilenameW, *FString::Printf(TEXT("unreal-v%i-%s.dmp"), FEngineVersion::Current().GetChangelist(), *FDateTime::Now().ToString()));
GIsConsoleExecutable = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR);
#endif
int32 ErrorLevel = EnginePreInit( CmdLine );
// exit if PreInit failed.
if ( ErrorLevel != 0 || IsEngineExitRequested() )
{ return ErrorLevel;
}
{ FScopedSlowTask SlowTask(100, NSLOCTEXT("EngineInit", "EngineInit_Loading", "Loading..."));
// EnginePreInit leaves 20% unused in its slow task.
// Here we consume 80% immediately so that the percentage value on the splash screen doesn't change from one slow task to the next. // (Note, we can't include the call to EnginePreInit in this ScopedSlowTask, because the engine isn't fully initialized at that point) SlowTask.EnterProgressFrame(80);
SlowTask.EnterProgressFrame(20);
#if WITH_EDITOR
if (GIsEditor)
{ ErrorLevel = EditorInit(GEngineLoop);
} else
#endif
{
ErrorLevel = EngineInit();
} }
double EngineInitializationTime = FPlatformTime::Seconds() - GStartTime;
UE_LOG(LogLoad, Log, TEXT("(Engine Initialization) Total time: %.2f seconds"), EngineInitializationTime);
#if WITH_EDITOR
UE_LOG(LogLoad, Log, TEXT("(Engine Initialization) Total Blueprint compile time: %.2f seconds"), BlueprintCompileAndLoadTimerData.GetTime());
#endif
ACCUM_LOADTIME(TEXT("EngineInitialization"), EngineInitializationTime);
BootTimingPoint("Tick loop starting");
DumpBootTiming();
while( !IsEngineExitRequested() )
{ EngineTick();
}
TRACE_BOOKMARK(TEXT("Tick loop end"));
#if WITH_EDITOR
if( GIsEditor )
{ EditorExit();
}#endif
return ErrorLevel;
}
#endif
```
预初始化:
+ 在决定加载什么包,uplugin、uproject定义的包
+ uproject本质是一个json文件,preinit就是解析json并加载json文件中定义的包
让虚幻引擎注册这些模块的类,初始化必须的底层系统。
+ 需要让引擎启动起来,则需要一些底层的数据和类的支持
+ 一般顺序是由引擎自身控制
+ Core(数据类型 Log String Name 3DMath Delegates Layer )
+ CoreUObject ([[C++API/反射系统|反射系统]],序列化,资源加载,[[垃圾回收]],BlueprintScript)
+ InputCore 输入key
+ Engine 引擎、动画、网格、材质、特性、音效、关卡、Actor、World、GameMode Controller、Component 等等
+ UnrealED EditorApplication 编辑器
+ StateCore、 Slate (空间蓝图的基础) UILayout Fonts images icons Input Stying BaseWidgetType
LoadCoreModules
LoadPreInitModules
LoadStartUpCoreModules
先加载底层一些模块,底层的关键系统在此初始化和类型定义。
自定义的项目和插件的模块,有需要被提前加载的被加载。
接着一些更高级的关键系统,项目和插件加载。
最后一步才是自定义代码的加载。
```cpp
/**
* PreInits the engine loop
*/
int32 EnginePreInit( const TCHAR* CmdLine )
{
int32 ErrorLevel = GEngineLoop.PreInit( CmdLine );
return( ErrorLevel );
}
```
FModuleManager加载包(模块)管理者、单例类
游戏实例的初始化,在游戏引擎初始化时,便初始化了。
FEngineLoop:Init
UGameEngine:Start
UGameInstance:StartGameInstance
UEngine:BrowseDefaultMap
UEngine:LoadMap
UGameEngine 游戏引擎类,被初始化和启动
UGameInstance 被初始化和启动
UGameViewPortClient 游戏视口被创建
ULocalPlayer 表达全局唯一的玩家的概念被创建
EngineObject
--- LoadMap ---
GameObject
UWorld
Ulevel
AActor
UActorComponent
AGameMode
AGameSession
AGameState
AGameNetWork
APlayerController
APlayerState
# UE底层运行逻辑
LanchEngineLoop 提供了对引擎进行预初始化,初始化,更新和退出的调用机制。
Launch.cpp 是引擎的程序入口也就是Main 定义了EngineLoop 的全局变量,并调用响应的函数。
预初始化 是完成对引擎底层模块 插件模块和自定义模块的加载
初始化 实例化了GameEngine的全局变量,并定义了GameInstance ViewPort LocalPlayer
GameEngine在完成了变量的创建Init之后,会执行Start 帮助我们LoadMap
LoadMap创建了UWorld,UWorld才是GamePlay游戏开发框架的基础机制。
# GamePlay框架
World 和 Map 意义相同,可以互换,都表示一张地图或者一个世界。
而世界中,有多个Level或者一个Level组成
Level中可以不包含Actor 也可以包含多个Actor。
持久关卡会默认和World一起被加载,流送关卡在不同时间段显示或隐藏。
FWorldContext UWorld UGameInstance 三者可以相互获取,相互依存。
World会完成对游戏内的初始化工作。
加载Level 加载Level中的Actor 并给Actor 添加各个Component组件
AGameSession 会话类 处理登录连接请求,在线服务相关
AGameNetWorkManager 网络管理类
AGameMode 游戏规则类
AGameStateBase 游戏状态类
ULocalPlayer 和 PlayerController
ULocalPlayer是引擎里玩家的代表,再UEngine::init里创建
PlayerController是玩家在地图里的代表。
LocalPlayer是玩家的抽象化,PlayerController是玩家的具体化。
NetConnection 网络连接对象,表示一个远程的Player
[[UObject]]
![[Picture/UE.png]]