I’m writing a simple plug-in and have some values that I want to drive from Console Variables that can be set in the config files for the class.
The console variables themselves seem to work as expected. If I open up the console and change the variables, the behavior of the class accurately reflects what changed.
Where I’m running into issues is with the saving and loading of the variables.
I’ve set up a UDeveloperSettings class, and when I go to Project Settings and change a value, it properly saves the new value to the config. But when I restart the editor, instead of loading the console variable value from the config, it sets the console variable back to its default value, and when I enter the console variable in the console, it says ‘Last Set By Constructor’.
I’ve tried setting some different ECVF flags, but I get the same result every time, unless I use ECVF_CreatedFromIni, which causes a crash in DeveloperSettings on startup because it can’t find the console variable. I get the same crash if I try to create the console variables in the constructor of my actor class instead of globally in the actor class.
I’m not sure what I’m missing here.
Code snippets:
Global Console Variable Declarations in the CPP of my actor class:
static TAutoConsoleVariable<int32> CVarSmoothTime(
TEXT("sdn.SmoothTime"),
1,
TEXT("Sets whether to use a smooth or stepped sun update")
);
static TAutoConsoleVariable<float> CVarDayLength(
TEXT("sdn.DayLength"),
10.0f,
TEXT("Sets how many real-time minutes equal 24 in-game hours")
);
static TAutoConsoleVariable<float> CVarSeasonLength(
TEXT("sdn.SeasonLength"),
4.0f,
TEXT("Number of days for each season")
);
static TAutoConsoleVariable<float> CVarStepRate(
TEXT("sdn.TimeStep"),
1.0f,
TEXT("Number of seconds between updates when not using Smoothed sun update")
);
Header for settings class:
UCLASS(Config=SimpleDayNight, DefaultConfig, DisplayName = "Simple Day/Night Cycle")
class SIMPLE_DAYNIGHT_API USimpleDayNightSettings : public UDeveloperSettings
{
GENERATED_BODY()
public:
virtual FName GetContainerName() const override;
virtual FName GetCategoryName() const override;
virtual FName GetSectionName() const override;
virtual void PostInitProperties() override;
#if WITH_EDITOR
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
public:
UPROPERTY(EditAnywhere, Config, Category = "Optimization", meta=(ConsoleVariable = "sdn.SmoothTime", DisplayName = "Smooth Sun Movement"))
int SmoothTime = 1;
UPROPERTY(EditAnywhere, Config, meta = (ConsoleVariable = "sdn.DayLength"))
float LengthOfDay = 10;
UPROPERTY(EditAnywhere, Config, meta = (ConsoleVariable = "sdn.SeasonLength"))
float SeasonLength = 4;
UPROPERTY(EditAnywhere, Config, meta = (ConsoleVariable = "sdn.TimeStep"))
float SteppedTimeRate = 1;
};
In the CPP for the settings I’m just doing an ImportConsoleVariableValues in PostInitValues, and ExportValuesToConsoleVariables in PostEditChangeProperty.
I can get it to work if I iterate through the FProperties and ExportValuesToConsoleVariables in PostInitValues instead, but that feels like the wrong approach. Surely the variables in the config should be overriding the defaults in the constructor automatically?