Custom Game User Settings, exposing to Blueprint/Casting

Hi there,

I’m trying to extend the basic UGameUserSettings so I can add audio control, FOV Control and other general graphic options. I created my own class, made some functions, added some variables and set the engine to use my GameUserSettings class as default. When the game runs PIE/Standalone, I can see the variables in the corresponding .ini file.

Problem is, changing the variables/calling the methods are a bit tricky. Simply I can’t call them in Blueprint. Calling the Get Game User Settings node, returns a default engine class, but I’m not able to cast it for my own custom made one. Does anyone have any idea/tips or trick to fix this problem. I tried nearly everything, no luck. Maybe I’m just missing something.

I’m posting the code, maybe that’s helps.

Header file:

#define HGAMEUSERSETTINGS_VERSION 8	// UE settings + 3

UENUM(BlueprintType)
enum class EVolumeType : uint8
{
	EVT_Master		UMETA(DisplayName="Master Volume"),
	EVT_Ambient		UMETA(DisplayName="Ambient Volume"),
	EVT_Dialog		UMETA(DisplayName="Dialog Volume"),
	EVT_Effect		UMETA(DisplayName="Effect Volume"),
	EVT_Music		UMETA(DisplayName="Music Volume"),
};

/**
 *
 */
UCLASS(config = HGameUserSettings, configdonotcheckdefaults)
class HAUNTEDGAME_API UHGameUserSettings : public UGameUserSettings
{
	GENERATED_UCLASS_BODY()

public:
	/** 
	* Sets the volume value for the given category for audio output.
	* @Param	VolumeCategory	Category to set volume for.
	* @Param	NewVolume		The new value for the volume.
	*/
	UFUNCTION(BlueprintCallable, Category = HauntedSettings)
	void SetAudioCategoryVolume(EVolumeType VolumeCategory, float NewVolume);

	/** Gets the Master Volume value. */
	UFUNCTION(BlueprintPure, Category = HauntedSettings)
	float GetMasterVolume() const { return MasterVolume; }

	/** Gets the Ambient Volume value. */
	UFUNCTION(BlueprintPure, Category = HauntedSettings)
	float GetAmbientVolume() const { return AmbientVolume; }

	/** Gets the Dialog Volume value. */
	UFUNCTION(BlueprintPure, Category = HauntedSettings)
	float GetDialogVolume() const { return DialogVolume; }

	/** Gets the Effect Volume value. */
	UFUNCTION(BlueprintPure, Category = HauntedSettings)
	float GetEffectVolume() const { return EffectVolume; }

	/** Gets the Music Volume value. */
	UFUNCTION(BlueprintPure, Category = HauntedSettings)
	float GetMusicVolume() const { return MusicVolume; }

protected:
	// Wipes serialized data if version is invalid
	virtual bool IsVersionValid();
	virtual void UpdateVersion();

	/** Master volume value */
	UPROPERTY(config)
	float MasterVolume;

	/** Ambient volume value */
	UPROPERTY(config)
	float AmbientVolume;

	/** Dialog volume value */
	UPROPERTY(config)
	float DialogVolume;

	/** Effect volume value */
	UPROPERTY(config)
	float EffectVolume;

	/** Music volume value */
	UPROPERTY(config)
	float MusicVolume;
};

Cpp File:

#include "UI/HGameUserSettings.h"

UHGameUserSettings::UHGameUserSettings(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	MasterVolume = 1.0f;
	AmbientVolume = 0.8f;
	DialogVolume = 0.65f;
	EffectVolume = 0.75f;
	MusicVolume = 0.9f;
}

void UHGameUserSettings::SetAudioCategoryVolume(EVolumeType VolumeCategory, float NewVolume)
{
	switch (VolumeCategory)
	{
	case EVolumeType::EVT_Master:
		MasterVolume = NewVolume;
		break;
	case EVolumeType::EVT_Ambient:
		AmbientVolume = NewVolume;
		break;
	case  EVolumeType::EVT_Dialog:
		DialogVolume = NewVolume;
		break;
	case EVolumeType::EVT_Effect:
		EffectVolume = NewVolume;
		break;
	case EVolumeType::EVT_Music:
		MusicVolume = NewVolume;
		break;
	}
}

bool UHGameUserSettings::IsVersionValid()
{
	return (Version == HGAMEUSERSETTINGS_VERSION);
}

void UHGameUserSettings::UpdateVersion()
{
	Version = HGAMEUSERSETTINGS_VERSION;
}

And the DefaultEngine.ini file:

[/Script/Engine.Engine]
WorldSettingsClassName=/Script/HauntedGame.HWorldSettings
GameUserSettingsClassName=/Script/HauntedGame.HGameUserSettings
1 Like

Your stuff seems right and I don’t know if I ever had a similar problem, but there is an easy way to bypass it. Just write your own static Blueprint-callable function that returns your user settings directly. This is how we’ve handled it in our projects.

MyUserSettings.h:

UCLASS(config=GameUserSettings)
class MYGAME_API MyUserSettings: public UGameUserSettings
{
	GENERATED_BODY()

public:
   UFUNCTION(BlueprintPure)
   static UMyUserSettings* GetUserSettings();
   ...
};

MyUserSettings.cpp:

UMyUserSettings* UMyUserSettings::GetUserSettings()
{
	return Cast<UMyUserSettings>(UGameUserSettings::GetGameUserSettings());
}
2 Likes

Works like a charm. I totally forgot to try this solution. Thanks for the respond!