Inheriting from UCommonSessionSubsystem

Hej, we implemented our own UMyUserBasicPresence and UMySessionSubsystem by inheriting from UCommonUserBasicPresence and UCommonSessionSubsystem. The problem is that there seems to be an issue with returning a child class via SubsystemCollection. It doesn’t find the parent if child class is in the list. We are running into the ensure condition, when common presence is trying to access the CommonSessionSubsystem.

void UMyUserBasicPresence::Initialize(FSubsystemCollectionBase& Collection)
{
	UMySessionSubsystem* MySessionSubsystem = Collection.InitializeDependency<UMySessionSubsystem>();
	check(MySessionSubsystem ); // Is there another child type of this instance? Check ShouldCreateSubsystem()

	Super::Initialize(Collection);
}

Engine\Plugins\Epic\CommonUser\Source\CommonUser\Private\CommonUserBasicPresence.cpp

void UCommonUserBasicPresence::Initialize(FSubsystemCollectionBase& Collection)
{
	UCommonSessionSubsystem* CommonSession = Collection.InitializeDependency<UCommonSessionSubsystem>();
	if(ensure(CommonSession)) // <-- THIS IS THE ISSUE, because it's NULL
	{
		CommonSession->OnSessionInformationChangedEvent.AddUObject(this, &UCommonUserBasicPresence::OnNotifySessionInformationChanged);
	}
}

CommonSession in the above case is a nullptr. I did a divergency fix on our end, but would like to get some feedback or ask for a real fix.

Engine/Source/Runtime/Engine/Private/Subsystems/SubsystemCollection.cpp

void FSubsystemCollectionBase::Initialize(UObject* NewOuter)
{
	if (BaseType->IsChildOf(UDynamicSubsystem::StaticClass()))
		{
            ...
		}
		else
		{
			TArray<UClass*> SubsystemClasses;
			GetDerivedClasses(BaseType, SubsystemClasses, true);

			for (UClass* SubsystemClass : SubsystemClasses)
			{
// DIVERGENCY BEGIN
				bool bIsFinalOverride = true;
				for (UClass* OtherSubsystemClass : SubsystemClasses)
				{
					if (SubsystemClass != OtherSubsystemClass && OtherSubsystemClass->IsChildOf(SubsystemClass))
					{
						bIsFinalOverride = false;
						break;
					}
				}

				if (bIsFinalOverride)
				{
					AddAndInitializeSubsystem(SubsystemClass);
				}
				else
				{
					UE_LOG(LogSubsystemCollection, Verbose, TEXT("Skip initializing subsystem, because it's not the final override %s"), *GetNameSafe(SubsystemClass));
				}
// DIVERGENCY END
				}
			}
		}

edit:
I am aware of this code in CommonSessionSubsystem

bool UCommonSessionSubsystem::ShouldCreateSubsystem(UObject* Outer) const
{
	TArray<UClass*> ChildClasses;
	GetDerivedClasses(GetClass(), ChildClasses, false);

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

Instead of the above code, we can also go with that solution. I am not sure which one is the best solution.


			if (CDO->ShouldCreateSubsystem(Outer))
			{
				...
			}
// DIVERGENCY BEGIN
			else
			{
				TArray<UClass*> ChildClasses;
				GetDerivedClasses(SubsystemClass, ChildClasses, false);

				for (auto ChildClass : ChildClasses)
				{
					if (SubsystemMap.Contains(ChildClass))
					{
						UE_LOG(LogSubsystemCollection, VeryVerbose, TEXT("Subsystem does not exist, but CDO choose to not create (%s). Returning ChildClass instead"), *ChildClass->GetName());
						return SubsystemMap.FindRef(ChildClass);
					}
				}				
			}
// DIV END