Configuring Subsystems via editor?

I had the same problem with World Subsystem, but found a semi-standard way to ensure the blueprints are initialized through a Native subsystem. I did this for World Subsystems but it should work for other types.

/** Settings Object that you need to register on your game/plugin module's startup. */
UCLASS(config = Game, defaultconfig)
class UBlueprintSubsystemSettings : public UObject
{
	GENERATED_BODY()
public:
	UPROPERTY(Config, EditAnywhere)
	TArray<TSubclassOf<UWorldSubsystem>> BlueprintSubsystems;
};

/**
 * Blueprint subsystems are not discovered by the world on load.
 * This subsystem only exists to load the other subsystems in the world
 */
UCLASS()
class UWorldSubsystemBPInitializer : public UWorldSubsystem 
{
	GENERATED_BODY()
	virtual void Initialize(FSubsystemCollectionBase& Collection) override
	{
		const UBlueprintSubsystemSettings* Settings = GetDefault<UBlueprintSubsystemSettings>();
		for(auto Subsystem : Settings->BlueprintSubsystems)
		{
			Collection.InitializeDependency(Subsystem);
		}
	}
};

You need to register your custom settings in your module to get it to show up in the project settings.

void FYourGameModule::StartupModule()
{
	if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
	{
		auto SettingsSection = SettingsModule->RegisterSettings("Project", "Game", "Subsystems",
																NSLOCTEXT("YourModule","BlueprintSubsystemSettingsName", "Blueprint World Subsystems"),
																NSLOCTEXT("YourModule","BlueprintSubsystemSettingsDesc",
																		"Add Blueprint Subsystems"),
																GetMutableDefault<UBlueprintSubsystemSettings>());

		// Register the save handler to your settings, you might want to use it to
		// validate those or just act to settings changes.
		if (SettingsSection.IsValid())
		{
			SettingsSection->OnModified().BindRaw(this, &FYourGameModule::HandleBlueprintSubsytemSettingsSaved);
		}
	}
}

void FYourGameModule::ShutdownModule()
{
	if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
	{
		SettingsModule->UnregisterSettings("Project", "Game", "Subsystems");
	}
}

bool FYourGameModule::HandleBlueprintSubsytemSettingsSaved()
{
	UBlueprintSubsystemSettings* Settings = GetMutableDefault<UBlueprintSubsystemSettings>();
	bool Resave = false;

	// You can put any validation code in here and resave the settings in case an invalid
	// value has been entered

	if (Resave)
	{
		Settings->SaveConfig();
	}

	return true;
}
10 Likes