UE4中提供了一套非常成熟的INI文件配置机制,引擎中也使用了ini作为引擎和项目的配置文件。本篇文章来简单分析一下引擎中GConfig的加载。
UE中定义了一堆的全局ini:
1 | // Runtime/Core/Private/Misc/CoreGlobals.cpp |
但是并没有直接硬编码指定ini是在哪里的,其加载的过程为:在FEngineLoop::AppInit
(LaunchEngineLoop.cpp)中通过调用FConfigCacheIni::InitializeConfigSystem
来执行加载ini文件,其定义在ConfigCacheIni.cpp
:
FConfigCacheIni::InitializeConfigSystem
1 | // -------------------------------- |
FConfigCacheIni::LoadGlobalIniFile
1 | // -------------------------------- |
FConfigCacheIni::LoadLocalIniFile
1 | // -------------------------------- |
FConfigCacheIni::LoadExternalIniFile
1 | // -------------------------------- |
这个函数中最重要的部分就是调用了GetSourceIniHierarchyFilenames
,它把当前传入的baseName的ini在Engine和项目下的所有ini文件都收集了起来。
这就是为什么我们看到其实GConfig中很多都是Saved/Config
下的ini,里面内容是空的,但是我们怎么查到项目里的设置的呢?这是因为UE把这么多个ini合并了:
这些ini的的内容都会加载进来。
这部分操作是在FConfigFile::AddStaticLayersToHierarchy
中实现的,通过遍历GConfigLayers
中所有规则的ini文件:
1 | struct FConfigLayer |
在使用时会进行替换:
1 | static FString PerformBasicReplacements(const FString& InString, const TCHAR* BaseIniName) |
比如我要加载Windows平台Game的ini,它实际上会包含:
1 | ../../../Engine/Config/Base.ini |
注意:GConfigLayers的最后一个元素具有
EConfigLayerFlags::GenerateCacheKey
的FLAG,在处理时会将所有的ini路径拼接起来作为Key:
1 | // add this to the list! |
最终所有能够被加载的Ini文件的路径列表,在GenerateDestIniFile
函数中执行实际的加载行为。(以Engine为例):
加载ini文件的栈:
读取时会按照Ini路径列表的顺序依次读取并Combine到FConfigFile
,这也表明了Ini文件的优先级也是如列表加载顺序。
GetDestIniFilename
1 | // Runtime/Source/Core/Private/Misc/ConfigCacheIni.cpp |
而FPaths::GeneratedConfigDir
获取的路径是当前项目的Saved
下的Config:
1 | // Paths.cpp |
即在Windows平台上项目启动时创建的全局G*Ini
文件读取的都是Saved/Config/Windows
下的.ini
。
而且在GetDestIniFilename
的实现中也可以看到,G*Ini
的配置也是可以从CommandLine传入的,可以替换掉默认的Saved/Config/Platform
下的ini:
1 | // 使用指定的Engine.ini |
扩展阅读