How can I create custom categories in GameUserSettings.ini?

I’m trying to separate my settings into specific categories in GameUserSettings.ini for organization. I’ve got the default GameUserSettings to change to my custom one but I’m not seeing the ‘audio’ category that I listed.

I’d like for it to look something like…

[/Script/IronGame.IronGameUserSettings]
bUseVSync=False
bUseDynamicResolution=False
... // rest of the default settings

[/Script/IronGame.IronGameAudioSettings] // Or something similar to this
MasterVolume=1.000000
MusicVolume=1.000000
SFXVolume=1.000000
UIVolume=1.000000

Here’s what I’ve got…

UCLASS(Config = GameUserSettings)
class IRONGAME_API UIronGameUserSettings_Audio : public UObject
{
	GENERATED_BODY()

public:

	UIronGameUserSettings_Audio();

	UFUNCTION(BlueprintCallable)
	void SetShowSubtitles(bool NewValue)
	{
		bShowSubtitles = NewValue;
	};

	UFUNCTION(BlueprintPure)
	bool GetShowSubtitles() const
	{
		return bShowSubtitles;
	};

	UFUNCTION(BlueprintCallable)
	void SetMusicVolume(float NewValue)
	{
		MusicVolume = NewValue;
	};

	UFUNCTION(BlueprintPure)
	float GetMusicVolume() const
	{
		return MusicVolume;
	};

	UFUNCTION(BlueprintCallable)
	void SetEffectsVolume(float NewValue)
	{
		EffectsVolume = NewValue;
	};

	UFUNCTION(BlueprintPure)
	float GetEffectsVolume() const
	{
		return EffectsVolume;
	};

	UFUNCTION(BlueprintCallable)
	void SetSpeechVolume(float NewValue)
	{
		SpeechVolume = NewValue;
	};

	UFUNCTION(BlueprintPure)
	float GetSpeechVolume() const
	{
		return SpeechVolume;
	};

protected:

	UPROPERTY(Config)
	bool bShowSubtitles;

	UPROPERTY(Config)
	float MusicVolume;

	UPROPERTY(Config)
	float SpeechVolume;

	UPROPERTY(Config)
	float EffectsVolume;
	
};

/**
 * IronGameUserSettings
 */
UCLASS(Config = GameUserSettings)
class IRONGAME_API UIronGameUserSettings : public UGameUserSettings
{
	GENERATED_UCLASS_BODY()

public:

	UFUNCTION(BlueprintCallable)
	static UIronGameUserSettings* GetIronGameUserSettings()
	{
		return Cast<UIronGameUserSettings>(GetGameUserSettings());
	}

	UFUNCTION(BlueprintCallable)
	UIronGameUserSettings_Audio* GetAudioSettings() const
	{
		return AudioSettings;
	}

private:

	UPROPERTY()
	TObjectPtr<UIronGameUserSettings_Audio> AudioSettings;
	
};

I tried to add the ‘Config’ value to my private pointer to the Audio class but it’s throwing an error that I can’t reference object types.

Yeah, unfortunately you can’t do that sort of thing with config properties/classes.

Option 1: Move your audio settings into IronGameUserSettings. The GameUserSettings usually becomes a union of all the player configurable values. If you look in GameUserSettings you’ll already see tons of different graphics settings.

Option2: Change AudioSettings to a structure instead. You would get any nice forward declaration behavior, but you would be able to collect all the related properties in a block that you could pass around like a pointer (if that’s why you’re doing it this way).

These are just off the top of my head. I would say option one is the usual approach.

I think it is possible, just don’t know how. I say that because I’ve noticed it in other game .ini files.

For example, if I check out the GameUserSettings.ini for Bellwright, a game on Steam made in UE:

[/Script/Mist.MistUserGameSettings]
bHardTownbuilderDifficulty=False
bShowSubtitles=True
bShowAttackArrows=True
bDisplayDamageInformation=False
// ... bunch of other variables

[/Script/Mist.MistUserSoundSettings]
MasterVolume=0.142000
MusicVolume=1.000000
SFXVolume=1.000000
UIVolume=1.000000
NarratorVolume=1.000000
VoiceOverVolume=1.000000
// ... etc

[/Script/Mist.MistUserInputSettings]
MouseSensitivity=0.250000
MouseDragSensitivity=1.000000
bInvertYAxis=False
bShowLocalizedKeys=False
bEnableMouseSmoothing=False
MinimapZoomScale=1.000000
CameraZoomValues=(("Player_C:FollowCameraSpringArmComponent", 250.000000))
// ... etc

Maybe these are just part of the same big UGameUserSettings but split into separate categories based on UPROPERTY somehow. I’ll try it out later when I can.

It’s not, the error that you’re getting is because hard references (raw pointers and TObjectPtr) are not supported as config properties.

Those examples actually prove exactly the opposite. Those are completely separate classes, not object instances nested inside a game user settings. If they were nested, you’d see the values in a way that would be similar to structures. Not with separate sections.

One possible setup:
A UMasterGameSettings derived from UGameUserSettings. This would be the class that is configured in DefaultEngine.ini.
Other settings classes are derived from UGameUserSettings. Not referenced by DefaultEngine.ini.
UMasterGameSettings has object references (not config) to the other settings classes.
In the constructor, UMasterGameSettings creates default subobjects for each of the object references.
You would then have to override various virtual functions on UMasterGameSettings (ApplySettings, SaveSettings, etc) and call the matching function of the subobjects.

But I don’t know if that’s really any better than just using structure properties that are just marked as config and then just work. But it’s all about tradeoffs.