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;
}