蓝图里获取配置信息
// DeveloperSettings.Build.cs #include "Kismet/BlueprintFunctionLibrary.h" #include "xxx.generated.h" UCLASS(Config=Game, defaultconfig) class UMySettings : public UDeveloperSettings { GENERATED_BODY() public: UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "General") bool DisableScreenMessages = false; // 在蓝图里可以直接访问该变量(GetClassDefaults) /** Gets the settings container name for the settings, either Project or Editor */ virtual FName GetContainerName() const override { return TEXT("Project"); } /** Gets the category for the settings, some high level grouping like, Editor, Engine, Game...etc. */ virtual FName GetCategoryName() const override { return TEXT("Game"); } /** The unique name for your section of settings, uses the class's FName. */ virtual FName GetSectionName() const override { return TEXT("General"); } }; UCLASS() class UMyBPLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, Category = "MyBP") static bool GetGameConfig(const FString& Section, const FString& Key, FString& Val); UFUNCTION(BlueprintCallable, Category = "MyBP") static bool DumpGameConfig(); }; bool UMyBPLibrary::GetGameConfig(const FString& Section, const FString& Key, FString& Val) { if (GConfig == nullptr) { return false; } FString ConfigFilePath = FPaths::ProjectDir() + TEXT("GameConfig/GameConfig.ini"); ConfigFilePath = FPaths::ConvertRelativePathToFull(ConfigFilePath); return GConfig->GetString(*Section, *Key, Val, ConfigFilePath); } bool UMyBPLibrary::DumpGameConfig() { if (GConfig == nullptr) { return false; } FString ConfigFilePath = FPaths::ProjectDir() + TEXT("GameConfig/GameConfig.ini"); ConfigFilePath = FPaths::ConvertRelativePathToFull(ConfigFilePath); UE_LOG(LogTemp, Log, TEXT("Dumping GameConfig file: [%s] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"), *ConfigFilePath); TArray<FString> OutSectionNames; bool bOk = GConfig->GetSectionNames(ConfigFilePath, OutSectionNames); for(auto s: OutSectionNames) { TArray<FString> OutResult; GConfig->GetSection(*s, OutResult, ConfigFilePath); UE_LOG(LogTemp, Log, TEXT("Section: [%s]"), *s); for(auto line: OutResult) { UE_LOG(LogTemp, Log, TEXT("key-value: %s"), *line); } UE_LOG(LogTemp, Log, TEXT("End Section <<<<<<<<<<<<<<<<<")); } UE_LOG(LogTemp, Log, TEXT("End Dumping <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")); return bOk; }
config/配置存取
UCLASS(Config=AnjGameSettings, ConfigDoNotCheckDefaults/DefaultConfig) class UAnjGameSettings : UDevelopSettings // [OR] UEditorSettings [OR] class AAnjGameSettings : Axxx { UPROPERTY(Config) int BroadcastPort = 8888;
AAnjGameSettings(); /** Gets the settings container name for the settings, either Project or Editor */ virtual FName GetContainerName() const override { return TEXT("Project"); } /** Gets the category for the settings, some high level grouping like, Editor, Engine, Game...etc. */ virtual FName GetCategoryName() const override { return TEXT("DataDrivenSettings"); } /** The unique name for your section of settings, uses the class's FName. */ virtual FName GetSectionName() const override { return TEXT("DataDrivenSettings"); } }
代码中Config=AnjGameSettings用来设定class中带有Config meta信息的Property要写入AnjGameSettings.ini文件。参考官网文档,这个Config叫做Specifier,指定Configuration Categories,Categories列表在官网能看到。
AAnjGameSettings()构造函数可以用来设定Property的默认值:
AAnjGameSettings()构造函数可以用来设定Property的默认值:
UAnjGameSettings::UAnjGameSettings( ) { if (GConfig) { FString IPStr; if (!GConfig->GetString(TEXT("/Script/SuraForAnj.AnjGameSettings"), TEXT("LocalIP"), IPStr, GetClass()->GetConfigName())) { bool canBind = false; TSharedRef<FInternetAddr> localIp = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetLocalHostAddr(*GLog, canBind); FIPv4Endpoint LocalEndpoint = FIPv4Endpoint(localIp); LocalIP = LocalEndpoint.Address.ToString(); SaveConfig(); } } }
注意上面代码中的GetClass()->GetConfigName(),它返回Config指定的AnjGameSettings.ini文件的存储路径(也可以直接写GGameIni、GEngineIni等值)。SaveConfig()是UObject的函数,注意其Filename参数未指定时,内部实现是设定为GetClass()->GetConfigName()。
ConfigDoNotCheckDefaults与DefaultConfig的区别:
UpdateDefaultConfigFile()函数类似上面的SaveConfig(),但会把值写入AnjGameSettingsDefault.ini文件。而在调用SaveConfig()时,如为DefaultConfig,则当Property的值与xxxDefault.ini文件里的值一致时,xxx.ini文件里Property属性行会被删除,这是因为xxxDefault.ini文件先被读取,然后是xxx.ini,所以与xxxDefault.ini里一致的属性,没必要再往xxx.ini写一条记录。而指定了ConfigDoNotCheckDefaults时,SaveConfig()不检查有无Default.ini文件及里面的属性值,直接更新xxx.ini文件。
UpdateDefaultConfigFile()函数类似上面的SaveConfig(),但会把值写入AnjGameSettingsDefault.ini文件。而在调用SaveConfig()时,如为DefaultConfig,则当Property的值与xxxDefault.ini文件里的值一致时,xxx.ini文件里Property属性行会被删除,这是因为xxxDefault.ini文件先被读取,然后是xxx.ini,所以与xxxDefault.ini里一致的属性,没必要再往xxx.ini写一条记录。而指定了ConfigDoNotCheckDefaults时,SaveConfig()不检查有无Default.ini文件及里面的属性值,直接更新xxx.ini文件。
从UDeveloperSettings派生的UObject,可以继承其能够在UE编辑器的ProjectSettings/EditorPreferences->Category->Section->(UPROPERTY.Category)里直接编辑属性的能力。
- GetContainerName():返回TEXT("Project")或者TEXT("Editor"),标识属性要在Project Settings菜单还是Editor Preferences菜单里设置。
- GetCategoryName():指定Settings界面的Category,比如Project Settings里的Project/Game/Plugins等。
- GetSectionName():指定该UObject的config属性要写入的界面段落,在该段落里面则是根据Property自己的Catogry meta信息来排布。
关于config信息的读取,参考:
To access the developer settings in C++ we use the CDO (Class Default Object) as that is already automatically instanced for us and accessed using GetDefault<T>();
To access the developer settings in C++ we use the CDO (Class Default Object) as that is already automatically instanced for us and accessed using GetDefault<T>();
void USSaveGameSubsystem::Initialize(FSubsystemCollectionBase& Collection) { Super::Initialize(Collection);
const USSaveGameSettings* SGSettings = GetDefault<USSaveGameSettings>(); // Access via CDO // Access defaults from DefaultGame.ini SlotName = SGSettings->SaveSlotName;
// Make sure it's loaded into memory .Get() only resolves if already loaded previously elsewhere in code UDataTable* DummyTable = SGSettings->DummyTablePath.LoadSynchronous(); }
有一个全部自定义处理config的参考
获取本地IP地址
// Module: Sockets.build.cs #include "SocketSubsystem.h" #include "IPAddress.h" #include "Interfaces/IPv4/IPv4Endpoint.h" bool canBind = false; TSharedRef<FInternetAddr> localIp = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetLocalHostAddr(*GLog, canBind); FIPv4Endpoint LocalEndpoint = FIPv4Endpoint(localIp); LocalIP = LocalEndpoint.Address.ToString();
ini文件读写
https://blog.51cto.com/hanzhichao/3201113 from configparser import ConfigParser conf = ConfigParser() conf.read(configFilePath, encoding=cur_encoding) print(conf['section']['key']) ''' LutConfig.py ''' from pathlib import Path from typing import * import chardet from configparser import ConfigParser def GetDefaultConfigFilePath() -> Path: return Path(__file__).parent.absolute() / 'Windows/TestLutPro/Config/DefaultGame.ini' def GetConfig(configFilePath: str) -> dict: # 首先二进制方式打开文件 with open(configFilePath, 'rb') as frb: # 检测编码方式 cur_encoding = chardet.detect(frb.read())['encoding'] # 指定文件编码方式 conf = ConfigParser() conf.read(configFilePath, encoding=cur_encoding) configResult = {} section = '/Script/ApplyLutTools.ApplyLutSettings' if conf.has_option(section, 'ServerIP'): configResult['ServerIP'] = conf[section]['ServerIP'] if conf.has_option(section, 'ServerPort'): configResult['ServerPort'] = conf[section].getint('ServerPort') if conf.has_option(section, 'LocalListeningIP'): configResult['LocalListeningIP'] = conf[section]['LocalListeningIP'] return configResult def GetDefaultConfig() -> dict: return GetConfig(GetDefaultConfigFilePath())