【UE4】引擎配置文件原理学习笔记
创始人
2024-03-29 08:23:46
0

刚好遇到一个ini加载的优化。趁此机会记录学习一下UE引擎的config文件层级结构和读取流程

文章目录

  • 两个问题
  • 层级结构
  • 文件读取流程
    • 初始化流程
    • 文件读取流程
    • 文件的写入
  • 配置文件内容和GConfig结构

两个问题

在看项目目录结构的时候,有没有这样的疑问:
为什么saved同级目录下面有一个config,saved里面还有一个config:saved/config?它们有什么区别吗?
在这里插入图片描述

看虚幻读配置文件的源码:发现它读取配置文件用的是一个LoadExternalIniFile的函数。但这个函数执行了读操作以外,还进行了写操作。为什么虚幻加载配置文件的以后还要写文件?
在这里插入图片描述

层级结构

实际上,UE采用的config配置文件读取策略是以层级的形式,可以分为以下四个层级:

  1. Engine/Config
  2. Engine/Saved/Config
  3. [ProjectName]/Config
  4. [ProjectName]/Saved/Config

加载一个名为"ConfigFileName"的config文件的时候,UE会依次遍历这些目录。后读取的覆盖前面的,即:其优先级依次递增。

这个层级的概念很有意思。颇有点子类复写的味道:如果项目内的目录就有ConofigFileName这个ini,就使用项目内的ini。否则使用其父层级引擎目录的ConofigFileName.ini。

保证了修改一个项目的ini不会影响到别的项目,没修改的部分依然沿用通用的设置。

UE会读到的配置文件目录记录于ConfigCacheIni.cpp的GConfigLayers中:

// ConfigCacheIni.cpp
GConfigLayers[] =
{/****************************************************** CRITICAL NOTES**** If you change this array, you need to also change EnumerateConfigFileLocations() in ConfigHierarchy.cs!!!**** And maybe UObject::GetDefaultConfigFilename(), UObject::GetGlobalUserConfigFilename()**************************************************/// Engine/Base.ini{ TEXT("AbsoluteBase"),				TEXT("{ENGINE}/Config/Base.ini"), EConfigLayerFlags::Required | EConfigLayerFlags::NoExpand},// Engine/Base*.ini{ TEXT("Base"),						TEXT("{ENGINE}/Config/Base{TYPE}.ini") },// Engine/Platform/BasePlatform*.ini{ TEXT("BasePlatform"),				TEXT("{ENGINE}/Config/{PLATFORM}/Base{PLATFORM}{TYPE}.ini")  },// Project/Default*.ini{ TEXT("ProjectDefault"),			TEXT("{PROJECT}/Config/Default{TYPE}.ini"), EConfigLayerFlags::AllowCommandLineOverride | EConfigLayerFlags::GenerateCacheKey },// Project/Generated*.ini Reserved for files generated by build process and should never be checked in { TEXT("ProjectGenerated"),			TEXT("{PROJECT}/Config/Generated{TYPE}.ini"), EConfigLayerFlags::GenerateCacheKey },// Engine/Platform/Platform*.ini{ TEXT("EnginePlatform"),			TEXT("{ENGINE}/Config/{PLATFORM}/{PLATFORM}{TYPE}.ini") },// Project/Platform/Platform*.ini{ TEXT("ProjectPlatform"),			TEXT("{PROJECT}/Config/{PLATFORM}/{PLATFORM}{TYPE}.ini") },// Project/Generated*.ini Reserved for files generated by build process and should never be checked in { TEXT("ProjectPlatformGenerated"),	TEXT("{PROJECT}/Config/{PLATFORM}/Generated{PLATFORM}{TYPE}.ini") },// UserSettings/.../User*.ini{ TEXT("UserSettingsDir"),			TEXT("{USERSETTINGS}Unreal Engine/Engine/Config/User{TYPE}.ini"), EConfigLayerFlags::NoExpand },// UserDir/.../User*.ini{ TEXT("UserDir"),					TEXT("{USER}Unreal Engine/Engine/Config/User{TYPE}.ini"), EConfigLayerFlags::NoExpand },// Project/User*.ini{ TEXT("GameDirUser"),				TEXT("{PROJECT}/Config/User{TYPE}.ini"), EConfigLayerFlags::GenerateCacheKey | EConfigLayerFlags::NoExpand },
};

文件读取流程

初始化流程

读进来的ini配置文件都被缓存在全局变量GConfig里。
在这里插入图片描述

文件读取流程

在这里插入图片描述
其中主要的耗时在读配置和写配置这两个位置。

文件的写入

UE在进行了上述的层级遍历以后,会得到一份最后生效的配置文件。它将这个文件的内容写入Saved目录中。

只从Engine/Config中读取,子层级没有复写的文件,写入Engine/Saved/Config中。否则写入[ProjectName]/Saved/Config中。注意这边的写入只写有差异的部分。

对于某个property的写入,如果这个property的值与其class的CDO相同,则没有存储多份的必要,不会写入配置文件。

为了遍历以确保不存储多份相同信息,写操作内涵多个嵌套的for遍历。如果ini文件非常大,ConfigFile.Write这个操作可能会花费非常多的时间。

所以我们的第一个问题就解决了:带Saved的路径下文件是运行时写入的,不带Save的是原有配置,用于读取的。

  1. Engine/Config【原有配置】
  2. Engine/Saved/Config【引擎运行后写入】
  3. [ProjectName]/Config【原有配置】
  4. [ProjectName]/Saved/Config【项目运行后写入】

这里有一个疑问:为什么在初始化加载ini文件的时候还需要写入到saved?虽然UE在写入的操作内部进行了比较,如果跟自己父层级的内容没有不一样的地方,就不写入saved目录下。但初始化加载的时候理论上刚刚加载到GConfig的内容是不会被修改的

配置文件内容和GConfig结构

打开一个配置文件可以看到其结构:
在这里插入图片描述
抽象出来一个ConfigFile的文件结构如下:
在这里插入图片描述
GConfig也是完全按照这个结构来构造的:
在这里插入图片描述
GConfig是一个以文件名作为key值的TMap;FConfigFile是一个以Section名作为Key的TMap,而FConfigSection则是每个Section下面的键值对。

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...