1. 为什么我们需要自定义配置文件?
在Unreal Engine(虚幻引擎)里做项目,尤其是稍微复杂点的游戏,你肯定遇到过这样的场景:游戏里有个“全局音量”滑块,玩家调好了,下次进游戏还得重新拉一遍;或者你作为开发者,在编辑器里调好了一堆测试参数,结果一关编辑器,全没了,第二天上班又得重新设。这种体验,无论是给玩家还是给自己,都挺糟心的。
这时候,配置文件(Config File)就是你的救星。它本质上就是一个文本文件(通常是.ini格式),用来持久化保存各种设置和参数。引擎本身就用它来存一大堆东西,比如项目设置、编辑器偏好、输入映射等等。但引擎自带的配置类别是固定的,如果我们想存一些自己游戏特有的数据,比如“角色默认皮肤ID”、“关卡解锁进度”、“自定义键位”,或者是一些只在开发期用的“上帝模式开关”、“刷怪倍率”,就需要自己动手,创建和管理自定义的配置文件。
你可能会想,我用SaveGame对象存不行吗?当然可以,但那通常用于存档数据,流程上需要你手动创建对象、序列化、保存到槽位。而配置文件系统更轻量、更“自动”。它最大的优势是与UObject属性系统深度集成。你可以像定义普通变量一样,在C++类里声明一个属性,然后通过简单的元数据标记,告诉引擎:“嘿,这个变量要和配置文件挂钩”。之后,引擎会在合适的时机(比如对象初始化时)自动从文件读取值,你也可以一键将内存中的值写回文件。这种声明式的用法,让代码非常干净,管理起来也省心。
所以,掌握自定义配置文件的读写,是UE开发中一项非常实用且能显著提升开发效率和游戏体验的基础技能。无论你是想为玩家保存个性化设置,还是为自己打造高效的开发工具链,这都是一块绕不开的内容。
2. 核心基石:UObject、UCLASS与Config元数据
要玩转自定义配置,首先得理解UE赖以生存的反射系统和UObject体系。别怕,我们不用钻得太深,知道怎么用就行。
2.1 创建一个可配置的UObject类
一切从一个继承自UObject的C++类开始。我们把它做成可配置的,关键就在UCLASS宏里的config说明符。
// MyGameConfig.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyGameConfig.generated.h"
UCLASS(config=MyGameSettings, BlueprintType)
class MYGAME_API UMyGameConfig : public UObject
{
GENERATED_BODY()
public:
UMyGameConfig();
// 这是一个可配置的浮点属性,同时可以在编辑器细节面板中编辑
UPROPERTY(Config, EditAnywhere, Category="Game Settings")
float MasterVolume;
// 一个可配置的字符串,比如存玩家名字
UPROPERTY(Config, EditAnywhere, Category="Game Settings")
FString PlayerName;
// 一个可配置的布尔值,用于开关功能
UPROPERTY(Config, EditAnywhere, Category="Debug")
bool bEnableDebugMode;
};
看上面这段代码,两个关键点:
UCLASS(config=MyGameSettings):这行是灵魂。config=后面跟的字符串MyGameSettings,指定了配置文件的“逻辑名称”。引擎最终会根据这个名称,在特定目录下寻找或创建名为MyGameSettings.ini的文件。这个名称你可以自己定,要有辨识度。UPROPERTY(Config, ...):在你想保存到文件的属性前,加上Config说明符。这就像给属性贴了个标签:“请把我和配置文件关联起来”。EditAnywhere是为了方便我们在编辑器的细节面板里也能直接修改它,这不是必须的,但通常很方便。
2.2 理解配置文件的加载与CDO
写好了类,值是怎么读进来的呢?这里涉及一个UE的核心概念:CDO(Class Default Object,类默认对象)。每个UClass在内存中都有一个单例的CDO,它存储了该类所有属性的默认值。
当你标记了Config的属性,引擎在构造这个类的CDO时,会做一件聪明事:它会去指定的配置文件里找对应的值。如果找到了,就用文件里的值覆盖代码里写的默认值;如果没找到,就保留代码里的默认值。
配置文件里的格式是固定的:
[/Script/你的项目名.你的类名]
属性名=属性值
假设我们的项目叫MyGame,类叫MyGameConfig,那么配置文件MyGameSettings.ini里应该长这样:
[/Script/MyGame.MyGameConfig]
MasterVolume=0.75
PlayerName="AwesomePlayer"
bEnableDebugMode=true
引擎就是通过[/Script/MyGame.MyGameConfig]这个“节(Section)”来定位到我们的类,然后根据属性名MasterVolume等来匹配和赋值的。
这意味着,你几乎不需要写“读取”代码。只要你的类正确设置,并且配置文件存在且格式正确,在游戏启动或编辑器加载时,CDO里的属性就已经是配置文件中保存的值了。你可以通过GetDefault<UMyGameConfig>()这个全局函数随时随地获取CDO,并读取里面的配置值。
// 在


797

被折叠的 条评论
为什么被折叠?



