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