1、UE4配置文件类型
UE4中,大量使用的配置文件类型并不是xml与json等新兴配置文件类型,而是使用相对古老的ini配置文件。
在UE4的目录中,专门有Config目录用于存放使用的ini配置文件。
2、配置文件的类型
在Config目录下有很多各种各样的配置文件,各个配置文件基本上代表的是一类配置。通过查看\Engine\Source\Runtime\Core\Public\Misc\ConfigCacheIni.h文件,可以帮助我们判断各个配置文件的作用。
在枚举类EConfigFileHierarchy中,对各个ini文件以及各个位置的ini配置文件的用途做了基本说明。
enum class EConfigFileHierarchy : uint8 { // Engine/Config/Base.ini AbsoluteBase = 0, // Engine/Config/*.ini EngineDirBase, // Engine/Config/Platform/BasePlatform* ini EngineDir_BasePlatform, // Engine/Config/NotForLicensees/*.ini EngineDirBase_NotForLicensees, // Engine/Config/NoRedist/*.ini -Not supported at this time. EngineDirBase_NoRedist, // Game/Config/*.ini GameDirDefault, // Game/Config/DedicatedServer*.ini GameDirDedicatedServer, // Game/Config/NotForLicensees/*.ini GameDirDefault_NotForLicensees, // Game/Config/NoRedist*.ini GameDirDefault_NoRedist, // Engine/Config/PlatformName/PlatformName*.ini EngineDir_Platform, // Engine/Config/NotForLicensees/PlatformName/PlatformName*.ini EngineDir_Platform_NotForLicensees, // Engine/Config/NoRedist/PlatformName/PlatformName*.ini EngineDir_Platform_NoRedist, // Game/Config/PlatformName/PlatformName*.ini GameDir_Platform, // Game/Config/NotForLicensees/PlatformName/PlatformName*.ini GameDir_Platform_NotForLicensees, // Game/Config/NoRedist/PlatformName/PlatformName*.ini GameDir_Platform_NoRedist, // <UserSettingsDir|AppData>/Unreal Engine/Engine/Config/User*.ini UserSettingsDir_EngineDir_User, // <UserDir|Documents>/Unreal Engine/Engine/Config/User*.ini UserDir_User, // Game/Config/User*.ini GameDir_User, // Number of config files in hierarchy. NumHierarchyFiles, };
3、ini文件的加载和解析
UE4中,使用类FConfigCacheIni来加载和管理系统中所使用的所有ini文件,可以通过该类来读取和设置ini文件中相应键值对。
3.1 FConfigCacheIni-配置文件系统
首先,我们来看一下FConfigCacheIni类的定义。
// Set of all cached config files. class CORE_API FConfigCacheIni : public TMap<FString,FConfigFile> { //接口函数已经省略,请自行查看代码 private: /** true if file operations should not be performed */ bool bAreFileOperationsDisabled; /** true after the base .ini files have been loaded, and GConfig is generally "ready for use" */ bool bIsReadyForUse; /** The type of the cache (basically, do we call Flush in the destructor) */ EConfigCacheType Type; };
可以看出,FConfigCacheIni实际上是由一组文件名-配置文件FConfigFile组成的Map加上表征配置文件系统状态和类型的变量bool bAreFileOperationsDisabled、bool bIsReadyForUse、EConfigCacheType Type组成的。
FConfigCacheIni类的访问具体键值的接口型如:
void SetInt//设置整型数值,通过指定ini文件、指定区段、指定键名称,设置该键为int值 ( const TCHAR* Section,//区段名 const TCHAR* Key,//键名 int32 Value,//值 const FString& Filename//ini文件名 ); bool GetInt//通过ini文件名,区段名,键名称获取该键对应的int值 ( const TCHAR* Section,//区段名 const TCHAR* Key,//键名 int32& Value,//输出int值 const FString& Filename//ini文件名 );
TConfigCacheIni类还有几个特殊的静态成员函数,用于执行整个配置文件缓存系统的初始化和配置文件的加载工作。
例如,在static void InitializeConfigSystem()中,完成了全局变量FConfigCacheIni*GConfig = nullptr所指向对象的创建和赋值工作。之后调用LoadGlobalIniFile、LoadExternalIniFile、LoadLocalIniFile、LoadConsoleVariablesFromINI进行ini文件的加载。
// Static helper functions static void InitializeConfigSystem(); static bool LoadGlobalIniFile(FString& FinalIniFilename, const TCHAR* BaseIniName, const TCHAR* Platform=NULL, bool bForceReload=false, bool bRequireDefaultIni=false, bool bAllowGeneratedIniWhenCooked=true, const TCHAR* GeneratedConfigDir = *FPaths::GeneratedConfigDir()); static bool LoadLocalIniFile(FConfigFile& ConfigFile, const TCHAR* IniName, bool bIsBaseIniName, const TCHAR* Platform=NULL, bool bForceReload=false); static bool LoadExternalIniFile(FConfigFile& ConfigFile, const TCHAR* IniName, const TCHAR* EngineConfigDir, const TCHAR* SourceConfigDir, bool bIsBaseIniName, const TCHAR* Platform=NULL, bool bForceReload=false, bool bWriteDestIni=false, bool bAllowGeneratedIniWhenCooked = true, const TCHAR* GeneratedConfigDir = *FPaths::GeneratedConfigDir()); static void LoadConsoleVariablesFromINI();
3.2 FConfigFile-配置文件
FConfigFile类用于表示一个ini配置文件。一个ini配置文件可以有多个区段组成,每个区段有自己的名称,因此,一个配置文件至少包含一个名称-区段的映射表。同时,一个配置文件还具有自己的文件名,配置文件类型的属性。
// One config file. class FConfigFile : public TMap<FString,FConfigSection> { public: bool Dirty, NoSave; /** The name of this config file */ FName Name; // The collection of source files which were used to generate this file. FConfigFileHierarchy SourceIniHierarchy; /** The untainted config file which contains the coalesced base/default options. I.e. No Saved/ options*/ FConfigFile* SourceConfigFile; /** Key to the cache to speed up ini parsing */ FString CacheKey; #if ALLOW_INI_OVERRIDE_FROM_COMMANDLINE /** The collection of overrides which stemmed from the commandline */ TArray<FConfigCommandlineOverride> CommandlineOptions; #endif // ALLOW_INI_OVERRIDE_FROM_COMMANDLINE };
通过一个配置文件对象,可以对该对象所表示的配置文件中的值进行读取和写入。读取和写入函数型如:
CORE_API void SetString( const TCHAR* Section, const TCHAR* Key, const TCHAR* Value ); CORE_API bool GetString( const TCHAR* Section, const TCHAR* Key, FString& Value ) const;
与上节中FConfigCacheIni类的接口不同的是,FConfigFile类的接口不在需要指定ini文件名。
3.3 FConfigSection-ini文件中的区段
一个ini文件的区段,是由一组或多组键值对组成的,所以从FConfigSection类是一个由键名称-值组成的映射表。注意它的MultiFind成员函数,从它的实现我们可以看出,UE4的配置文件中,是支持在同一个区段中,一个键的名称对应多个不同的值的,也就是说存在1-N的映射关系。
typedef TMultiMap<FName,FConfigValue> FConfigSectionMap; // One section in a config file. class FConfigSection : public FConfigSectionMap { public: /** * Check whether the input string is surrounded by quotes * * @param Test The string to check * * @return true if the input string is surrounded by quotes */ static bool HasQuotes( const FString& Test ); bool operator==( const FConfigSection& Other ) const; bool operator!=( const FConfigSection& Other ) const; // process the '+' and '.' commands, takingf into account ArrayOfStruct unique keys void CORE_API HandleAddCommand(FName Key, const FString& Value, bool bAppendValueIfNotArrayOfStructsKeyUsed); template<typename Allocator> void MultiFind(const FName Key, TArray<FConfigValue, Allocator>& OutValues, const bool bMaintainOrder = false) const { FConfigSectionMap::MultiFind(Key, OutValues, bMaintainOrder); } template<typename Allocator> void MultiFind(const FName Key, TArray<FString, Allocator>& OutValues, const bool bMaintainOrder = false) const { for (const TPair<FName, FConfigValue>& Pair : Pairs) { if (Pair.Key == Key) { OutValues.Add(Pair.Value.GetValue()); } } if (bMaintainOrder) { Algo::Reverse(OutValues); } } // look for "array of struct" keys for overwriting single entries of an array TMap<FName, FString> ArrayOfStructKeys; };
3.4 FConfigValue-配置的值
UE4配置文件系统FConfigCacheIni由多个FConfigFile组成,FConfigFile有多个FConfigSection组成,FConfigSection则由多个FConfigValue组成。FConfigValue是保存配置文件值的字面值的地方,也就意味着,在整个UE4的配置文件系统中,将所有从配置文件中读取的值都保存成了字符串,在需要使用的时候再通过相应的接口转变成所需要的类型,比如int等类型。
struct FConfigValue { // Returns the ini setting with any macros expanded out const FString& GetValue() const { #if WITH_EDITOR bRead = true; #endif return (ExpandedValue.Len() > 0 ? ExpandedValue : SavedValue); } // Returns the original ini setting without macro expansion const FString& GetSavedValue() const { #if WITH_EDITOR bRead = true; #endif return SavedValue; } private: /** Internal version of ExpandValue that expands SavedValue into ExpandedValue, or produces an empty ExpandedValue if no expansion occurred. */ void ExpandValueInternal() { if (!ExpandValue(SavedValue, ExpandedValue)) { ExpandedValue.Empty(); } } FString SavedValue; FString ExpandedValue; #if WITH_EDITOR mutable bool bRead; // has this value been read since the config system started #endif };
从中可以看出,FConfigValue保存的是FString类型的字符串。