06 - 配置文件
本文主要说明了UE5中有关配置文件的相关内容,包括:
DeveloperSettings
的简单运用;- 配置文件的类目,层级和基础语法;
- 使用
GConfig
手动读写.ini
配置文件;
配置文件用于配置启动时的Gameplay或引擎行为的初始设置。
DeveloperSettings 入门
DeveloperSettings
用于做项目级的配置管理,它可以把某些全局参数/配置暴露到编辑器的 项目设置 或 编辑器设置 面板中,并且能在运行时读取,而不是硬编码到代码或蓝图中。
编写设置类
要想使用该功能,需要在build.cs
中包含DeveloperSettings
模块,并编写一个继承自UDeveloperSettings
的U类:
XGSampleSettings.h点击展开/折叠代码
// ...
#include "Engine/DeveloperSettings.h"
// ...
// 可将结构体作为配置项
USTRUCT(BlueprintType)
struct FXGSampleDescriber
{
GENERATED_BODY()
public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "XGProjectInfo")
FString AuthorName = TEXT("XG");
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "XGProjectInfo")
bool bExperiment = false;
};
// vv 下述注释可显示在配置的介绍中 vv
/**
* UXGSampleSettings
* My Project Information
*/
UCLASS(Config = XGSampleSettings, defaultconfig)
class XGSAMPLEDEMO_API UXGSampleSettings : public UDeveloperSettings
{
GENERATED_BODY()
public:
// U类的默认构造函数
UXGSampleSettings(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
virtual ~UXGSampleSettings();
public:
// 配置存放的位置(项目设置, 编辑器设置等)
virtual FName GetContainerName() const override;
// 该配置的分类
virtual FName GetCategoryName() const override;
// 该配置的名字
virtual FName GetSectionName() const override;
public:
// 只读配置项
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "XG")
FString ProjectVersion =TEXT("1.0.0");
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "XG")
FXGSampleDescriber SampleDescriber;
// 可修改配置项
UPROPERTY(Config,EditAnywhere, BlueprintReadWrite, Category = "XG")
FString ProjectSimpleName = TEXT("1.0.0");
UPROPERTY(Config, EditAnywhere, BlueprintReadWrite, Category = "XG")
FString XGAppID = TEXT("None");
UPROPERTY(Config, EditAnywhere, BlueprintReadWrite, Category = "XG")
FString XGAppKey = TEXT("None");
}
XGSampleSettings.cpp点击展开/折叠代码
#include "XGSampleSettings.h"
UXGSampleSettings::UXGSampleSettings(const FObjectInitializer& ObjectInitializer)
:Super(ObjectInitializer) {}
UXGSampleSettings::~UXGSampleSettings()
{
}
FName UXGSampleSettings::GetContainerName() const
{
return TEXT("Project");
}
FName UXGSampleSettings::GetCategoryName() const
{
return TEXT("XG");
}
FName UXGSampleSettings::GetSectionName() const
{
return TEXT("XGSampleSettings");
}
其中,需要重写如下函数:
GetContainerName()
:该配置存放的位置(项目设置, 编辑器设置等)。GetCategoryName()
:该配置的分类。GetSectionName()
:该配置的名字。
然后添加一些自己需要的配置项即可,如果要编辑某些配置项,需要在它的UPROPERTY()
处添加Config
说明符。可修改的配置可以存储到DefaultXGSampleSettings.ini
中。
这样就能在项目设置中看到新添加的配置XG -> XG Sample Settings
:
它的配置项如下图所示:
读写设置
可通过C++代码方式读写配置项:
// 读配置项
if (UXGSampleSettings* XGSampleSettings = GetMutableDefault<UXGSampleSettings>())
{
OutMyAppKey = XGSampleSettings->XGAppKey;
}
else
{
OutMyAppKey = TEXT("None");
}
// 写配置项, 并保存到ini文件中
if (UXGSampleSettings* XGSampleSettings = GetMutableDefault<UXGSampleSettings>())
{
XGSampleSettings->XGAppKey = InMyAppKey;
// 保存到 Saved/Config 下的运行时配置
XGSampleSettings->SaveConfig();
// 保存并更新工程的 Default*.ini 文件, 文件名*取决于配置类的Config标识符内容
XGSampleSettings->TryUpdateDefaultConfigFile();
}
以上内容就是对配置类DeveloperSettings
的简单操作了,如果想要对配置进行进阶操作(如处理配置的层级关系等),需要对配置文件(.ini
)的类目、层级和语法进行一定的了解。
配置文件
配置文件类目
虚幻引擎可识别的配置文件类目主要如下:
通用
Engine
Game
Input
DeviceProfiles
GameUserSettings
Scalability
RuntimeOptions
InstallBundle
Hardware
GameplayTags
既适用于编辑器
Editor
EditorPerProjectUserSettings
EditorSettings
EditorKeyBindings
EditorLayout
仅适用于桌面版
Compat
Lightmass
配置文件层级
每个类目中可以有多个不同的配置文件。 例如,Engine
目录中包含:
Engine\Config\BaseGame.ini
Engine\Config\Windows\WindowsGame.ini
这些文件是 Game
配置文件类目的一部分,并且属于不同分层。
同一类目中的配置文件组织为一个分层结构。 如果同一类目中的文件之间存在重复的键/值对,则层级中后面出现的文件中的键/值分配将覆盖或添加层级中前面出现的文件中的键/值分配。层级结构从低到高依次为:
Engine/Config/Base.ini
Engine/Config/Base<CATEGORY>.ini
Engine/Config/<PLATFORM>/Base<PLATFORM><CATEGORY>.ini
Engine/Platforms/<PLATFORM>/Config/Base<PLATFORM><CATEGORY>.ini
<PROJECT_DIRECTORY>/Config/Default<CATEGORY>.ini
Engine/Config/<PLATFORM>/<PLATFORM><CATEGORY>.ini
Engine/Platforms/<PLATFORM>/Config/<PLATFORM><CATEGORY>.ini
<PROJECT_DIRECTORY>/Config/<PLATFORM>/<PLATFORM><CATEGORY>.ini
<PROJECT_DIRECTORY>/Platforms/<PLATFORM>/Config/<PLATFORM><CATEGORY>.ini
<LOCAL_APP_DATA>/Unreal Engine/Engine/Config/User<CATEGORY>.ini
<MY_DOCUMENTS>/Unreal Engine/Engine/Config/User<CATEGORY>.ini
<PROJECT_DIRECTORY>/Config/User<CATEGORY>.ini
更多相关内容详见Engine/Source/Runtime/Core/Public/Misc/ConfigHierarchy.h
。
配置文件语法
整体结构
配置文件(.ini
)的整体结构如下:
; 每个配置变量必须属于一个[SECTION],
; 并且必须包含KEY且后跟=符号
[SECTION1]
<KEY1>=<VALUE1>
<KEY2>=<VALUE2>
[SECTION2]
; 键值对的值可以为空
<KEY3>=
SECTION名称
分段名称为字母字符串,可以将其设置为任何值。 无论项目代码中是否存在配置变量,配置系统都会加载配置文件中的所有声明。
模块
模块中可配置对象的命名方式如下:
[/Script/ModuleName.ClassName]
其中:
ModuleName
:该模块的名称;ClassName
:该模块中可配置对象的类名;
插件
插件中可配置对象的命名方式如下:
[/Script/PluginName.ClassName]
其中:
PluginName
:该插件的名称;ClassName
:该插件中可配置对象的类名;
蓝图
蓝图中可配置资产的命名方式如下:
[/PathToUAsset/UAssetName.UAssetName_C]
其中:
PathToUAsset
:资产的路径。UAssetName
:资产的名称。
此外,还要在编辑器里对应蓝图变量的细节面板中勾选Config Variable
才能让对应变量应用配置。
自定义
还可以自定义分段名,但此后需要 手动将配置应用于对应变量 ,详见下文。
键值对
键值对的值可以表示各种不同类型的信息:
- 字符串:支持使用特殊转义字符、十六进制值和UTF序列。 这有助于进行本地化和国际化;
- 数字;
- 数组;
- 结构体;
数组
配置文件支持下列数组操作:
名称 | 运算符 | 描述 | 示例 |
---|---|---|---|
清空(Empty) | ! | 清空数组的内容。 = 后面的任何值都会被忽略。 为避免产生歧义,建议在 = 之后添加一些描述性内容,如 !MyVar=ClearArray 。 | !MyArray=ClearArray |
附加(Append) | + | 如果数组中还不存在该值,将该值附加到数组中。 如果数组中已存在该值,则不执行任何操作。 | +MyArray=Value |
删除(Remove) | - | 从数组中删除该值。 必须是完全匹配项。 | -MyArray=Value |
附加重复项(Append Duplicate) | . | 即使数组中已经存在该值,也要将该值附加到数组中。 | .MyArray=Value |
例如有如下数组操作:
; 从数组中删除所有内容,然后附加7,即初始化
MyConfigArray=7
; 清除数组的所有条目
!MyConfigArray=ClearArray
; 向数组附加2, 3, 4
+MyConfigArray=2
+MyConfigArray=3
+MyConfigArray=4
; 向数组强制添加重复项2
.MyConfigArray=2
; 从数组删除4
-MyConfigArray=4
那么最后数组MyConfigArray
元素为[2, 3, 2]
。
结构体
设置结构体的语法为:
[/Script/MyModule.MyClass]
MyStruct=(MyStructProperty1=Value1,MyStructProperty2=Value2,...)
使用GConfig读写配置文件
函数
在Engine/Source/Runtime/Core/Public/Misc/ConfigCacheIni.h
中有读写相关的函数:
Set/GetBool
Set/GetInt
Set/GetInt64
Set/GetFloat
Set/GetDouble
Set/GetString
Set/GetText
Set/GetArray
配置类目
配置类目的标识为 G<CATEGORY>Ini
。 例如,Engine
类目表示为 GEngineIni
。更多相关信息可以在 Engine/Source/Runtime/Core/Public/CoreGlobals.h
中找到。
例子
假设有如下DefaultGame.ini
:
[MyCategoryName]
MyVariable=2
那么使用GConfig
读写该自定义分段的方式如下:
// 读取
int MyConfigVariable;
GConfig->GetInt(TEXT("MyCategoryName"), TEXT("MyVariable"), MyConfigVariable, GGameIni);
// 写入
GConfig->SetInt(TEXT("MyCategoryName"), TEXT("MyVariable"), MyConfigVariable, GGameIni);
GCOnfig->Flush(false, GGameIni);