UE-引擎入口与主循环

本文介绍了Unreal Engine 5在Windows平台的应用程序入口,主要流程包括EnginePreInit、EngineInit、EngineTick和EngineExit四个阶段。在EnginePreInit中,进行引擎启动初始化;EngineInit则涉及引擎及其子类的初始化,包括广播引擎初始化、模块加载等;EngineTick是引擎主循环,执行场景更新、帧同步等关键任务;EngineExit则处理退出流程。详细探讨了EngineTick中的游戏引擎Tick函数及其调用过程。
摘要由CSDN通过智能技术生成

对于Windows平台,WinMain为应用程序入口;
WinMain所在的源文件为:

Engine/Source/Launch/Private/Windows/LaunchWindows.cpp

int32 WINAPI WinMain(_In_ HINSTANCE hInInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ char* pCmdLine, _In_ int32 nCmdShow)
{
   
	int32 Result = LaunchWindowsStartup(hInInstance, hPrevInstance, pCmdLine, nCmdShow, nullptr);
	LaunchWindowsShutdown();
	return Result;
}

LaunchWindowsStartup中调用GuardedMainWrapper继而调用GuardedMain进入引擎整体的调用流程:

int32 GuardedMain( const TCHAR* CmdLine )
{
   
	FTrackedActivity::GetEngineActivity().Update(TEXT("Starting"), FTrackedActivity::ELight::Yellow);
	// 省略部分代码
	FTrackedActivity::GetEngineActivity().Update(TEXT("Initializing"));
	// 执行PreInit
	int32 ErrorLevel = EnginePreInit( CmdLine );
	// 省略部分代码
	// 执行Init
#if WITH_EDITOR
		if (GIsEditor)
		{
   
			ErrorLevel = EditorInit(GEngineLoop);
		}
		else
#endif
		{
   
			ErrorLevel = EngineInit();
		}
	}
	FTrackedActivity::GetEngineActivity().Update(TEXT("Ticking loop"), 			FTrackedActivity::ELight::Green);

	// Don't tick if we're running an embedded engine - we rely on the outer
	// application ticking us instead.
	if (!GUELibraryOverrideSettings.bIsEmbedded)
	{
   
		while( !IsEngineExitRequested() )
		{
   
			// 执行Tick
			EngineTick();
		}
	}

	TRACE_BOOKMARK(TEXT("Tick loop end"));

#if WITH_EDITOR
	if( GIsEditor )
	{
   
		EditorExit();
	}
#endif
	return ErrorLevel;
}

这其中主要进行是引擎主线程的整个生命周期:
1. EnginePreInit
2. EngineInit
3. EngineTick
4. EngineExit

而这四步调用中都是通过一个全局对象FEngineLoop GEngineLoop调用到文件

\Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp

中的对应接口。

1. EnginePreInit
EnginePreInit中进行了一系列的引擎启动初始化准备工作,其中包括
为每个继承自UObject的对象创建CDO对象:

	// Make sure all UObject classes are registered and default properties have been initialized
		{
   
			UE_SCOPED_ENGINE_ACTIVITY(TEXT("Initializing UObject Classes"));
			ProcessNewlyLoadedUObjects();
		}

ProcessNewlyLoadedUObjects位于:

\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectBase.cpp

void ProcessNewlyLoadedUObjects(FName Package, bool bCanProcessNewlyLoadedObjects)
{
   
	//省略部分代码
	bool bNewUObjects = false;
	TArray<UClass*> AllNewClasses;
	while (GFirstPendingRegistrant ||
		ClassRegistry.HasPendingRegistrations() ||
		StructRegistry.HasPendingRegistrations() ||
		EnumRegistry.HasPendingRegistrations())
	{
   
		bNewUObjects = true;
		UObjectProcessRegistrants();
		UObjectLoadAllCompiledInStructs();

		FCoreUObjectDelegates::CompiledInUObjectsRegisteredDelegate.Broadcast(Package);
		//为每个继承自`UObject`的对象创建CDO对象
		UObjectLoadAllCompiledInDefaultProperties(AllNewClasses);
	}
	//省略部分代码
}
/**
 * Load any outstanding compiled in default properties
 */
static void UObjectLoadAllCompiledInDefaultProperties(TArray<UClass*>& OutAllNewClasses)
{
   
	//省略部分代码
	{
   
			SCOPED_BOOT_TIMING("CoreUObject Classes"
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用 `vue-element-admin` 框架时,可以通过 `vue-i18n` 插件来实现国际化,同时也可以将字典数据封装成组件,方便在不同页面和组件中复用。 以下是实现字典数据封装的一般步骤: 1. 在 `src/lang` 目录下创建字典文件,例如 `zh.js` 和 `en.js`,并在文件中定义字典数据: ```javascript // zh.js export default { dict: { yes: '是', no: '否' } } // en.js export default { dict: { yes: 'Yes', no: 'No' } } ``` 2. 在 `src/lang/index.js` 文件中引入字典文件,并将字典数据注入到 `vue-i18n` 插件中: ```javascript import Vue from 'vue' import VueI18n from 'vue-i18n' import zh from './zh' import en from './en' Vue.use(VueI18n) const messages = { zh: { ...zh }, en: { ...en } } const i18n = new VueI18n({ locale: 'zh', messages }) export default i18n ``` 3. 创建字典组件 `Dict`,并在组件中使用 `vue-i18n` 插件来获取字典数据: ```vue <template> <span>{{ dict[label] }}</span> </template> <script> export default { name: 'Dict', props: { label: { type: String, required: true } }, computed: { dict() { return this.$i18n.messages[this.$i18n.locale].dict } } } </script> ``` 4. 在需要使用字典的页面或组件中,使用 `Dict` 组件并传入需要翻译的标签: ```vue <template> <div> <p>{{ $t('dict.yes') }}</p> <p>{{ $t('dict.no') }}</p> <Dict label="yes" /> <Dict label="no" /> </div> </template> <script> import Dict from '@/components/Dict' export default { name: 'Example', components: { Dict } } </script> ``` 这样,就可以在页面或组件中通过 `Dict` 组件来获取字典数据,实现字典数据的封装和复用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值