This is a bug in the Meta XR plugin, but as someone who develops a different Unreal Engine plugin whose use of dynamic config layers is being interfered with due to this API behaviour, I believe this should count as a bug in the engine as well.
In the Meta XR plugin, they unconditionally call UpdateSinglePropertyInConfigFile inside UOculusXRHMDRuntimeSettings::PostInitProperties(), which means it always happens during startup because this class is used for default config and exposed in Project Settings. This causes all dynamic layers in the config system to be removed, such that they don’t exist after the editor has launched (Snipping Tool is a screenshot from launching with the Meta XR plugin enabled):
[Image Removed]
The implementation of UpdateSinglePropertyInConfigFile looks not great in the context of the config branch overhaul that happened in the last few engine versions. It flushes the config and uses FConfigContext::ForceReloadIntoGConfig() / Load, neither of which seem like they would safe when happening in a startup context where configuration is still being loaded for CDOs.
I think two things need to happen here:
At a minimum, UpdateSinglePropertyInConfigFile needs an checkf() if it’s being called while CDOs are being loaded, or ProcessNewlyLoadedUObjects is happening. This would prevent other developers from misusing this API during PostInitProperties.
UpdateSinglePropertyInConfigFile should be looked at to see whether or not it’s doing the right thing with the new branch code, and perhaps this function should be deprecated/removed entirely.
[Attachment Removed]
Run the engine normally, observe that dynamic config layers are present in memory.
Enable the Meta XR plugin for Unreal Engine, which unconditionally calls UpdateSinglePropertyInConfigFile inside UOculusXRHMDRuntimeSettings::PostInitProperties.
Observe that no dynamic config layers exist once the editor is up and running.
[Attachment Removed]
It looks like UpdateSinglePropertyInConfigFile is unsafe to call at any time. I commented out it’s usage during PostInitProperties and observed the dynamic layers were intact. Then I went into Project Settings and triggered another call to it, and observed that the dynamic layers get removed at that point:
[Image Removed]
So adding a checkf is not enough; the implementation of UpdateSinglePropertyInConfigFile needs to be fixed so it doesn’t remove dynamic layers or the function needs to be deprecated & removed entirely.
Oh dear, I am surprised I haven’t heard/realized this before!
Well we certainly aren’t going to remove it! The editor depends on it to edit Project Settings correctly.
I actually have replaced how it works with a method to directly save the property to the static layer (usually DefaultFoo.ini). It isn’t in 5.6, and 5.7 has it disabled by default, but the new cvar “ini.UseNewPropertySaving” will activate the fix for this issue. I am actually planning on defaulting it to 1 for 5.8, now that I am pretty confident it won’t cause issues. Can you wait until you get a new engine version?
[mention removed] Heads up, I am having reports from downstream customers that ini.UseNewPropertySaving is causing other Project Settings to not be saved as normal. This is from customers that are at least using P4, so I’m wondering if there’s some interaction there that I haven’t observed with Git.
Still investigating and don’t currently have a reproduction, but thought I’d flag it in case it’s being turned on by default for 5.8.
I can confirm setting ini.UseNewPropertySaving to 1 in Unreal Engine 5.7 solves the issue (UpdateSinglePropertyInConfigFile no longer causes dynamic layers to be removed).
I’ll update our plugin to automatically set it to 1 on startup to protect against other plugins using UpdateSinglePropertyInConfigFile, though this won’t help anyone on 5.6 or earlier (which Meta Quest folks currently are). Once they upgrade to 5.7 though, we’ll be able to workaround it with the ini.UseNewPropertySaving property automatically.
If these files do exist, does removing them make the issue go away?
Does Saved/Config/ exist in the project and/or engine directories? Does it have files in it? If you remove that folder, does the issue go away?
Their response was that none of the files exist but the language and timezone are different between them and their team members. I’ve asked them to change their team member language/timezone to match their own, and we’ll see if it goes away.
Whatever the underlying cause here is, it seems to be machine/environment dependent, not project dependent.
So, no files are being saved at all? That seems unrelated to the way properties are being chosen to save… but it’s definitely the case that the ini.UseNewPropertySaving is causing this?
Correct, with the exception of the Redpoint EOS Project Settings (and that’s because we have our own INI file writing logic and don’t use UpdateSinglePropertyInConfigFile).
When the team members turn off ini.UseNewPropertySaving then changing settings in Project Settings causes settings to be written to disk again.
It’s extremely bizarre that it only impacts some people, but I haven’t been able to get anyone affected to step through the save code with a debugger and see the state of variables as the new save logic runs.
The new prop saving should only affect things like the writing Defaults, not Saved/Config/Foo.ini, so the lack of those files is okay.
Maybe some logging in ModifyAndWriteLayer and/or FSinglePropertyConfigHelper::UpdatePropertyInSection(), and in UObject::SaveConfig where SetArrayInSectionOfStaticLayer/SetInSectionOfStaticLayer are called will help diagnose after the fact.