【UE4】引擎配置文件原理学习笔记

news2025/1/12 12:03:28

刚好遇到一个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<FString,FConfigFile>;FConfigFile是一个以Section名作为Key的TMap<FString,FConfigSection>,而FConfigSection则是每个Section下面的键值对。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/74958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

喜报!泛睿云国家版权局颁发的软件著作权证书

近日,泛睿云自主研发的泛睿云计算服务平台V1.0,通过中国人民共和国国家版权局权威授权,获得了计算机软件著作权登记证书,这是对泛睿云实力和研发水平的充分肯定。 软件著作权是企业核心自主知识产权,是企业的“无形资产”,是企业科技的生命力和价值所在,国家权威部门的认证将使…

微信群裂变文案微信群裂变软件

看过前几篇文章的&#xff0c;想必多多少少都清楚微信群裂变以及朋友圈裂变能够带来的巨大能量&#xff1a;低成本获客&#xff0c;高质量传播。那今天就来分享微信群以及微信朋友圈裂变话术&#xff0c;满满都是干货&#xff0c;新手一定要看仔细咯。今天的内容主要讲的有三点…

亲测有效!咳嗽3秒检测新冠的小·程·序;开源啦!超全的AI创作工具网站;谷歌乳腺癌AI筛查进入临床实践;根据文字生成音乐 | ShowMeAI资讯日报

&#x1f440;日报合辑 | &#x1f3a1;AI应用与工具大全 | &#x1f514;公众号资料下载 | &#x1f369;韩信子 &#x1f4e2; 『Thinkit声音识别』亲测有效&#xff01;新冠病毒咳嗽声检测小程序 一款名为“Thinkit声音识别”的微信小程序&#xff0c;实现通过声音识别新冠…

c#入门-可为空的注释上下文

null 一个经典的问题&#xff0c;字符串的“”和null有什么区别。 string s null; string s2 ""; Console.WriteLine(s); Console.WriteLine(s2);虽然看起来&#xff0c;他们都没有储存实际数据。 区别在于&#xff0c;“”相当于买了0个月饼。别人发了个空盒子过…

编译原理:词法分析

参考视频&#xff1a;方舟编译技术入门与实战 以及 西交冯博琴老师的相关视频 编译的过程包括 词法分析&#xff08;分析程序符号&#xff09;、语法分析&#xff08;分析语法单位&#xff09;、中间代码生成、代码优化和目标代码生成。该架构自1960s之后基本未变。 一、编译过…

FFMPEG读取本地文件推流到RTMP服务器!

前言&#xff1a; 今天我们再来分享一个开源代码项目&#xff0c;这个代码项目是通过读取本地的TS文件&#xff0c;然后推流到RTMP服务器上面。一、项目框图和运行效果&#xff1a; 1.1.项目的框图&#xff1a;1.2.运行效果&#xff1a;二、模块的讲解&#xff1a; 2.1.初始化文…

做了6年的软件测试了,想提升一下自己,学一下自动化测试,但是没有方向,怎么办?

前言 最后后台一位粉丝和我说做了6年的功能测试&#xff0c;在职场没有突破涨薪&#xff0c;陷入了一个迷茫的境地&#xff0c;想学自动化测试但是又不知道从哪里入手&#xff01;&#xff01;&#xff01;今天静姐就带这位粉丝盘一盘自动化测试如何进阶&#xff1f;&#xff…

Python OpenCV 单目相机标定、坐标转换相关代码(包括鱼眼相机)

前言 本文不讲原理&#xff0c;只关注代码&#xff0c;有很多博客是讲原理的&#xff0c;但是代码最多到畸变矫正就结束了&#xff0c;实际上就是到 OpenCV 官方示例涉及的部分。   在官方示例中使用黑白棋盘格求解了相机的内外参和畸变系数&#xff0c;并对图像做了畸变矫正…

多态实现原理

学习Java的时候就已经学习了多态但是对于多态的原理还是不是很明白所以写下这篇文章来记录一下 如果后面有新的理解也继续添加到本页面 什么是多态 多态是面向对象编程里面的概念&#xff0c;一个接口的多种实现不同的实现方式&#xff0c;即为多态 这里的接口不应理解得太死板…

国考省考行测:关联词分析法,转折,总结,条件,递进,并列,各种关联词的典型词语和重点在哪

国考省考行测&#xff1a;关联词分析法&#xff0c;转折&#xff0c;总结&#xff0c;条件&#xff0c;递进&#xff0c;并列&#xff0c;各种关联词的典型词语和重点在哪 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&a…

Twitter营销你需要做的细节

优化首页 1. 塑造品牌形象 品牌对于企业来说是一种无形的价值&#xff0c;所以在任何平台上都要注意加深品牌印象&#xff0c;在推特上也是一样的&#xff0c;比如一样的logo&#xff0c;让访问过你网站的人一眼就认出你来。这样&#xff0c;品牌的不断深入&#xff0c;才能让…

如何用mac搭建本地svn服务器(如何将mac变成版本管理服务器)

前言 一、搭建本地svn服务器 1.建立代码库 2.配置文件修改 3.启动本地svn服务 二、搭建过程中常见问题 如果Mac os升级到10.0以上&#xff0c;自带的svn不支持了怎么办 三、mac本地使用svn软件管理svn库 cornerstone3安装 四、使用Cornerstone会存在的问题 Mac打开应用提示已损…

硬件 RAID 与软件 RAID 之间的区别

独立磁盘冗余阵列 &#xff08;RAID&#xff09; 是一种将多个物理驱动器组合到一个单元中的虚拟磁盘技术。这是一种通过使用多个驱动器来提高存储介质的性能和可靠性的方法。驱动器配置为在磁盘之间划分数据以分配负载&#xff0c;或者复制数据以确保在磁盘发生故障后可以恢复…

Oauth2.0实现单点登录的原理流程,这次总该懂了!

单点登录是多域名企业站点流行的登录方式。本文以现实生活场景辅助理解&#xff0c;力争彻底理清 OAuth2.0 实现单点登录的原理流程。同时总结了权限控制的实现方案&#xff0c;及其在微服务架构中的应用。 1 什么是单点登录 1.1 多点登录 传统的多点登录系统中&#xff0c;…

正大国际期货:外盘期货恒指八大交易法则!

现在比较流行的期货并不算多&#xff0c;主流的就是恒指期货、美原油期货和黄金期货还有德指期货、道指、铜、天然气等等&#xff0c;恒指期货是最适合亚洲人投资的期货品种&#xff0c;现在国内很多投资人也会选择恒指期货入手。那么投资者要遵循哪些法则才可能在期货市场中获…

安装虚拟机以及linux(Centos 7)系统

背景&#xff1a;模拟部署系统至Linux服务器上并运行 下载VMware Workstation Pro并激活&#xff0c;自行百度下载。 打开虚拟机“创建新的虚拟机” 然后选择自定义&#xff0c;选择好后点击下一步 直接下一步 稍后安装操作系统 客户机操作系统选择Linux&#xff0c;版本选择…

element集成第三方icon图标

引言 集成阿里图标库 进入阿里icon&#xff0c;新建项目 选择一个自己喜欢的icon库&#xff0c;将里面的图标加入购物车中 因为没有批量导入购物车&#xff0c;所以一般情况下需要一个一个去点&#xff0c;太浪费时间&#xff0c;那么请在控制台输入以下代码&#xff0c;批量…

Spring 中 @Bean 注解流程分析

代码案例 现在 SpringBoot、SpringCloud 基本上都是通过 Bean 注解来将组件交给 Spring 管理&#xff0c;所以对 Bean 的流程应该要有所了解。 这里先定义一个 Blue 的实体类&#xff0c;如下&#xff1a; public class Blue { }然后定义一个入口类&#xff0c;通过 Bean 注…

rocketMq介绍和安装

rocketMq介绍和安装 Mq介绍 MQ&#xff1a;MessageQueue&#xff0c;消息队列。 队列&#xff0c;是一种FIFO 先进先出的数据结构。消息由生产者发送到MQ进行排队&#xff0c;然后按原来的顺序交由消息的消费者进行处理。 QQ和微信就是典型的MQ。 MQ的作用 主要有以下三个…

天翼物联2项成果成功入选“工信部2022年移动物联网应用典型案例库”

近日&#xff0c;工信部公布了2022年移动物联网应用典型案例征集活动入库案例名单&#xff0c;天翼物联牵头申报的“智慧农业——水肥一体化物联网项目”、“智能表计——抄表机器人物联网项目”成功入选。 本次典型应用案例征集由工业和信息化部组织开展&#xff0c;征集范围包…