Proper way to derive from Common Subsystem

What is the proper way to derive from the Common Subsystem classes?

I tried to create a game specific version of CommonSessionSubsystem, but CommonUserBasicPresence complained about it.

void UCommonUserBasicPresence::Initialize(FSubsystemCollectionBase& Collection)
{
  UCommonSessionSubsystem* CommonSession = Collection.InitializeDependency<UCommonSessionSubsystem>();
  if(ensure(CommonSession))
  {
    CommonSession->OnSessionInformationChangedEvent.AddUObject(this, &UCommonUserBasicPresence::OnNotifySessionInformationChanged);
  }
}

The ensure was being triggered because InitializeDependency was not creating UCommonSessionSubsystem, which makes sense because UCommonSessionSubsystem has this section of code in it

  TArray<UClass *> ChildClasses;
  GetDerivedClasses(GetClass(), ChildClasses, false);

  // Only create an instance if there is not a game-specific subclass
  return ChildClasses.Num() == 0;

preventing it from being created when there is a derived class. I ended up doing something like this:

Collection.InitializeDependency<UCommonSessionSubsystem>();

  UCommonSessionSubsystem* CommonSession = GetGameInstance()->GetSubsystem<UCommonSessionSubsystem>();
  if(ensure(CommonSession))


to get around, but I didn’t know if there was a more correct way to do this without editing the common plugin

Hello there. I see that the UCommonSessionSubsystem code you called out which checks for child classes implies it’s meant to be extended by design.

However, the call to Collection.InitializeDependency<UCommonSessionSubsystem>() in UCommonUserBasicPresence will not try to look for any child classes. For the time being I recommend making the following change to UCommonUserBasicPresence so that it will find and initialize a subclass of CommonSessionSubsystem. I’ll ask internally whether we’d consider modifying the implementation of InitializeDependency to consider subclasses.

void UCommonUserBasicPresence::Initialize(FSubsystemCollectionBase& Collection)
{
	UCommonSessionSubsystem* CommonSession = Collection.InitializeDependency<UCommonSessionSubsystem>();
	
	// START MODIFICATION
	// Game code can make a subclass, preventing the parent class creation by design
	if (CommonSession == nullptr)
	{
		TArray<UClass*> CommonSessionSubsystemClasses;
		GetDerivedClasses(UCommonSessionSubsystem::StaticClass(), CommonSessionSubsystemClasses);
 
		for (UClass* ChildClass : CommonSessionSubsystemClasses)
		{
			CommonSession = Cast<UCommonSessionSubsystem>(Collection.InitializeDependency(ChildClass));
			if (CommonSession)
			{
				UE_LOG(LogTemp, Warning, TEXT("Initialized '%s' as CommonSessionSubsystem"), *ChildClass->GetName());
				break;
			}
		}
	}
	// END MODIFICATION
 
	if (ensure(CommonSession))
	{
		CommonSession->OnSessionInformationChangedEvent.AddUObject(this, &UCommonUserBasicPresence::OnNotifySessionInformationChanged);
	}
}

I’ll close this case. But to summarize the answer to your question: “What is the proper way to derive from the Common Subsystem classes?”

You didn’t miss a better way. Modifying UCommonUserBasicPresence to consider that UCommonSessionSubsystem might have been extended by the game project is currently the way.