UE4 Ini配置文件的层级

本文的重点:理解UE4的“Ini层级”概念,以及找到其对应代码,与观察运行结果。

官方文档中介绍的“层级”概念

官方文档icon-default.png?t=N7T8https://dev.epicgames.com/documentation/en-us/unreal-engine/configuration-files-in-unreal-engine?application_version=5.4 在UE4的官方文档中,搜索“Configuration File Hierarchy”小节,可以看到Ini配置文件的优先级层级如下:

Category configuration files are loaded in the following order:

  1. Engine/Config/Base.ini
  2. Engine/Config/Base<CATEGORY>.ini
  3. Engine/Config/<PLATFORM>/Base<PLATFORM><CATEGORY>.ini
  4. Engine/Platforms/<PLATFORM>/Config/Base<PLATFORM><CATEGORY>.ini
  5. <PROJECT_DIRECTORY>/Config/Default<CATEGORY>.ini
  6. Engine/Config/<PLATFORM>/<PLATFORM><CATEGORY>.ini
  7. Engine/Platforms/<PLATFORM>/Config/<PLATFORM><CATEGORY>.ini
  8. <PROJECT_DIRECTORY>/Config/<PLATFORM>/<PLATFORM><CATEGORY>.ini
  9. <PROJECT_DIRECTORY>/Platforms/<PLATFORM>/Config/<PLATFORM><CATEGORY>.ini
  10. <LOCAL_APP_DATA>/Unreal Engine/Engine/Config/User<CATEGORY>.ini
  11. <MY_DOCUMENTS>/Unreal Engine/Engine/Config/User<CATEGORY>.ini
  12. <PROJECT_DIRECTORY>/Config/User<CATEGORY>.ini

越往后的越高优先级,它对应的代码是:

/**
 * Structure to define all the layers of the config system. Layers can be expanded by expansion files (NoRedist, etc), or by ini platform parents
 * (coming soon from another branch)
 */
struct FConfigLayer
{
	// Used by the editor to display in the ini-editor
	const TCHAR* EditorName;
	// Path to the ini file (with variables)
	const TCHAR* Path;
	// Path to the platform extension version
	const TCHAR* PlatformExtensionPath;
	// Special flag
	EConfigLayerFlags Flag;

} 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}Base.ini"), TEXT(""), EConfigLayerFlags::Required },
	
	// Engine/Base*.ini
	{ TEXT("Base"),						TEXT("{ENGINE}{ED}{EF}Base{TYPE}.ini") },
	// Engine/Platform/BasePlatform*.ini
	{ TEXT("BasePlatform"),				TEXT("{ENGINE}{ED}{PLATFORM}/{EF}Base{PLATFORM}{TYPE}.ini"), TEXT("{EXTENGINE}/{ED}{EF}Base{PLATFORM}{TYPE}.ini"),  },
	// Project/Default*.ini
	{ TEXT("ProjectDefault"),			TEXT("{PROJECT}{ED}{EF}Default{TYPE}.ini"), TEXT(""), EConfigLayerFlags::AllowCommandLineOverride | EConfigLayerFlags::GenerateCacheKey },
	// Engine/Platform/Platform*.ini
	{ TEXT("EnginePlatform"),			TEXT("{ENGINE}{ED}{PLATFORM}/{EF}{PLATFORM}{TYPE}.ini"), TEXT("{EXTENGINE}/{ED}{EF}{PLATFORM}{TYPE}.ini") },
	// Project/Platform/Platform*.ini
	{ TEXT("ProjectPlatform"),			TEXT("{PROJECT}{ED}{PLATFORM}/{EF}{PLATFORM}{TYPE}.ini"), TEXT("{EXTPROJECT}/{ED}{EF}{PLATFORM}{TYPE}.ini") },
	
	// UserSettings/.../User*.ini
	{ TEXT("UserSettingsDir"),			TEXT("{USERSETTINGS}Unreal Engine/Engine/Config/User{TYPE}.ini") },
	// UserDir/.../User*.ini
	{ TEXT("UserDir"),					TEXT("{USER}Unreal Engine/Engine/Config/User{TYPE}.ini") },
	// Project/User*.ini
	{ TEXT("GameDirUser"),				TEXT("{PROJECT}User{TYPE}.ini"), TEXT(""), EConfigLayerFlags::GenerateCacheKey },
};

(代码块1)

其中的 {ED} {EF} 是用于替换的记号,{ED}表示文件夹的前缀,{EF}表示文件的前缀,代码位于

static FString GetExpansionPath(const FConfigLayerExpansion& Expansion, const FString& LayerPath, bool bHasPlatformTag)
{
	// replace the expansion tags
	FString ExpansionPath = LayerPath.Replace(TEXT("{ED}"), Expansion.DirectoryPrefix, ESearchCase::CaseSensitive);
	ExpansionPath = ExpansionPath.Replace(TEXT("{EF}"), Expansion.FilePrefix, ESearchCase::CaseSensitive);

替换的规则见 GConfigLayerExpansions[] 。因为代码很多很杂,接下来我找到了重点的代码进行学习和罗列。

代码示意图

我找到了重点代码,绘制了如下调用关系图:

其中的 “Final” 或说 “Dest” Ini的概念,对应的接口文档是:

https://docs.unrealengine.com/4.27/en-US/API/Runtime/Core/Misc/FConfigCacheIni/GetDestIniFilename/

其中MarkC处 AddStaticLayersToHierarchy() 的含义是:

一、第一层For循环:遍历各层级

    // go over all the config layers
    for (int32 LayerIndex = 0; LayerIndex < UE_ARRAY_COUNT(GConfigLayers); LayerIndex++)

见前文“代码块1”;

二、第二层For循环:遍历各平台

                for (int PlatformIndex = 0; PlatformIndex < NumPlatforms; PlatformIndex++)

例如安卓。实测没有看到 Android 等字样,不细究。

调试“加载Ini的过程”

1、在 void FConfigCacheIni::InitializeConfigSystem() 的最后一行 FCoreDelegates::ConfigReadyForUse.Broadcast() 处下断点;

2、以调试Game的方式(UE4如何直接调试Game-优快云博客)进行调试。

UE4加载Ini的堆栈是:

FConfigCacheIni::InitializeConfigSystem() ConfigCacheIni.cpp:3908
FEngineLoop::AppInit() LaunchEngineLoop.cpp:5716
FEngineLoop::PreInitPreStartupScreen(const wchar_t *) LaunchEngineLoop.cpp:2083
FEngineLoop::PreInit(const wchar_t *) LaunchEngineLoop.cpp:3593
[Inlined] FEngineLoop::PreInit(int, wchar_t **, const wchar_t *) LaunchEngineLoop.cpp:1104
wmain(int, wchar_t **) UnrealPak.cpp:13

UE_LOG(LogTemp, Warning, TEXT("MyCodeTrace:ConfigFile.Name:>>>>  %s"), * ConfigFile.Name.ToString());
// ConfigFile.Name
for(auto each 	 /* TMap<FString,FConfigSection> */ : ConfigFile.SourceIniHierarchy)
	{
			UE_LOG(LogTemp, Warning, TEXT("MyCodeTrace:WatchStaticLayers  %d : %s"), each.Key,  * each.Value.Filename);
	}
	UE_LOG(LogTemp, Warning, TEXT("MyCodeTrace:ConfigFile.Name:<<<<  %s"), * ConfigFile.Name.ToString());

通过添加日志的方式,如上,观察到 MarkC处 AddStaticLayersToHierarchy() 处添加的 Layers 是这些内容:

0 : ../../../Engine/Config/Base.ini
10000 : ../../../Engine/Config/BaseInput.ini
10200 : ../../../Engine/Config/ShippableBaseInput.ini
10300 : ../../../Engine/Config/NotForLicensees/BaseInput.ini
10400 : ../../../Engine/Config/NotForLicensees/ShippableBaseInput.ini
10500 : ../../../Engine/Config/NoRedist/BaseInput.ini
10600 : ../../../Engine/Config/NoRedist/ShippableBaseInput.ini
20000 : ../../../Engine/Config/Windows/BaseWindowsInput.ini
20200 : ../../../Engine/Config/Windows/ShippableBaseWindowsInput.ini
20300 : ../../../Engine/Config/NotForLicensees/Windows/BaseWindowsInput.ini
20400 : ../../../Engine/Config/NotForLicensees/Windows/ShippableBaseWindowsInput.ini
20500 : ../../../Engine/Config/NoRedist/Windows/BaseWindowsInput.ini
20600 : ../../../Engine/Config/NoRedist/Windows/ShippableBaseWindowsInput.ini
30000 : ../../../Engine/Programs/UnrealPak/Config/DefaultInput.ini
30200 : ../../../Engine/Programs/UnrealPak/Config/ShippableDefaultInput.ini
30300 : ../../../Engine/Programs/UnrealPak/Config/NotForLicensees/DefaultInput.ini
30400 : ../../../Engine/Programs/UnrealPak/Config/NotForLicensees/ShippableDefaultInput.ini
30500 : ../../../Engine/Programs/UnrealPak/Config/NoRedist/DefaultInput.ini
30600 : ../../../Engine/Programs/UnrealPak/Config/NoRedist/ShippableDefaultInput.ini
40000 : ../../../Engine/Config/Windows/WindowsInput.ini
40200 : ../../../Engine/Config/Windows/ShippableWindowsInput.ini
40300 : ../../../Engine/Config/NotForLicensees/Windows/WindowsInput.ini
40400 : ../../../Engine/Config/NotForLicensees/Windows/ShippableWindowsInput.ini
40500 : ../../../Engine/Config/NoRedist/Windows/WindowsInput.ini
40600 : ../../../Engine/Config/NoRedist/Windows/ShippableWindowsInput.ini
50000 : ../../../Engine/Programs/UnrealPak/Config/Windows/WindowsInput.ini
50200 : ../../../Engine/Programs/UnrealPak/Config/Windows/ShippableWindowsInput.ini
50300 : ../../../Engine/Programs/UnrealPak/Config/NotForLicensees/Windows/WindowsInput.ini
50400 : ../../../Engine/Programs/UnrealPak/Config/NotForLicensees/Windows/ShippableWindowsInput.ini
50500 : ../../../Engine/Programs/UnrealPak/Config/NoRedist/Windows/WindowsInput.ini
50600 : ../../../Engine/Programs/UnrealPak/Config/NoRedist/Windows/ShippableWindowsInput.ini
60000 : C:/Users/wenjiezou/AppData/Local/Unreal Engine/Engine/Config/UserInput.ini
70000 : C:/Users/wenjiezou/Documents/Unreal Engine/Engine/Config/UserInput.ini
80000 : ../../../Engine/Programs/UnrealPak/Config/UserInput.ini

其中,最先的是

0 : ../../../Engine/Config/Base.ini
10000 : ../../../Engine/Config/BaseInput.ini

最后(最终 / 最优先生效)的是:

70000 : C:/Users/wenjiezou/Documents/Unreal Engine/Engine/Config/UserInput.ini
80000 : ../../../Engine/Programs/UnrealPak/Config/UserInput.ini

但实际上并不一定具有这些文件,例如实际上就不存在 C:/Users/wenjiezou/Documents/Unreal Engine/Engine/Config/UserInput.ini 这个文件。

实际上观察到的最终Ini文件是空的,例如 G:\St\EngineSource\Engine\Programs\UnrealPak\Saved\Config\Windows\GameUserSettings.ini 的内容是空行,原因可以参考源代码中的注释,当引擎初始化的时候,其实不应该产生变化,因此不需要输出最终Ini。

		// Check GIsInitialLoad since no INI changes that should be persisted could have occurred this early.
		// INI changes from code, environment variables, CLI parameters, etc should not be persisted. 
		if (!GIsInitialLoad && bWriteDestIni && (!FPlatformProperties::RequiresCookedData() || bAllowGeneratedIniWhenCooked)
			// We shouldn't save config files when in multiprocess mode,
			// otherwise we get file contention in XGE shader builds.
			&& !FParse::Param(FCommandLine::Get(), TEXT("Multiprocess")))
		{
			// Check the config system for any changes made to defaults and propagate through to the saved.
			ConfigFile.ProcessSourceAndCheckAgainstBackup();

			if (bNeedsWrite)
			{
				// if it was dirtied during the above function, save it out now
				ConfigFile.Write(DestIniFilename);
			}
		}

那么最终的GConfig是怎么样的呢?它其实是Map映射  { 最终Ini名 → FConfigFile },

其中,FConfigFile是映射  {  Section名  →  众字段  } ,如下图所示:

总结

UE4采用“Ini层级”的概念,让引擎、项目具有默认的配置值、逐项目的配置值、逐实际运行的实例的配置值(Saved下)、甚至是和本地环境相关的配置值。本文还找到了相关代码与运行结果进行学习。

<think>好的,用户需要关于虚幻引擎中森林场景灯光效果的实现方法和教程。首先,我需要回顾一下已有的引用内容。引用[1]提到了虚幻引擎渲染的基本组件,比如镜头光晕、场模糊和晕影,这些在适度使用时能增强电影感。同时强调了烘焙照明的重要性,以及大场景中的LOD和剔除技术。引用[2]则提到了静态光照场景(static light scenarios)的使用,可能涉及不同光照设置的切换。 用户的需求是森林场景的灯光效果,所以需要结合自然光照的处理,比如动态的天空、阳光透过树叶的效果、雾效等。可能需要提到定向光作为主要光源,调整色温和强度来模拟自然光。体积雾和后期处理效果(如光晕、晕影)也是关键。引用[1]中提到的烘焙照明非常重要,尤其是对于静态物体,可以提升性能和视觉效果。同时,LOD和剔除技术有助于优化大场景,比如森林中的大量植被。 接下来,教程方面可能需要分步骤指导:设置基础光照、添加体积雾、调整后期处理、优化光照烘焙、使用LOD和剔除。此外,引用[2]中的静态光照场景可能适用于不同时间段的森林光照切换,比如清晨和黄昏,可以建议用户创建多个光照场景并学习如何切换它们。 需要注意用户可能遇到的性能问题,尤其是在密集的植被场景中,所以优化部分需要详细说明。同时,引用[1]提醒不要过度使用特效,保持自然感,这点也很重要。最后,应该推荐官方文档和社区资源,如Unreal Learn和ArtStation的教程,帮助用户深入学习。</think>### 虚幻引擎森林场景灯光效果实现方法 在虚幻引擎中实现森林场景的灯光效果,需结合自然光照、体积雾、后期处理等技术。以下是关键步骤和原理: #### 1. **基础光照设置** - **定向光(太阳光)**:使用`Directional Light`模拟阳光,调整色温(约5500K~6500K)和强度(10~20 lux),通过旋转角度控制光影方向[^2]。 - **天光(Sky Light)**:启用`Sky Light`捕捉环境光,勾选"Real Time Capture"实现动态天空反射。 - **IES光照文件**:对局部植被可使用带IES配置的`Spot Light`,模拟树叶间隙的光斑效果。 #### 2. **体积雾与大气效果** ```cpp // 在关卡中启用体积雾 VolumetricFog.bEnable = true; ExponentialHeightFog.FogDensity = 0.02; ``` 通过调整`Exponential Height Fog`的散射分布($I = I_0 e^{-\beta z}$),可模拟林间晨雾效果[^1]。 #### 3. **植被光照优化** - **逐顶点光照(VLM)**:为树木材质启用`Use Volumetric Lightmap`,提升动态植被光照精度。 - **距离场软阴影**:在项目设置中启用`Generate Mesh Distance Fields`,实现远距离树木的柔和阴影。 #### 4. **后期处理增强** ```ini [PostProcessVolume] BloomIntensity=0.8 LensFlareIntensity=0.6 VignetteIntensity=0.3 ``` 引用[1]建议适度使用镜头光晕和晕影,可增强场景层次感但需避免过度使用。 #### 5. **光照烘焙策略** - 对静态岩石、地形使用`Baked Lighting`,烘焙质量建议≥64 samples/pixel - 动态光源采用`Mixed Lighting`混合模式,通过`Lightmass Importance Volume`限定烘焙范围 $$ \Phi = \int_{\Omega} L_i(\omega) \cos\theta d\omega $$ 此辐射度量公式可用于验证全局光照强度分布。 #### 6. **性能优化方案** - **层级剔除(HLOD)**:对远景树木设置LOD 3+级,Draw Distance≤5000单位 - **植被代理渲染**:对灌木丛使用`Foliage Instanced Static Mesh`组件 - **光照通道分离**:将地形光照与角色光照分配不同Lighting Channels
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值