UE 5.6 Problem: GetSubsystem Only Returns First Opened Blueprint Class

UE5.6: Issue with Getting Blueprint Subsystem Classes After Engine Restart

Problem Description:

In UE5.6, after creating a C++ class that inherits from a subsystem (e.g., UGameInstanceSubsystem) and marking it as Blueprintable, then creating Blueprint classes that inherit from this C++ class, I encounter an issue every time I open the engine.

After launching the engine, I can only get one of the Blueprint-inherited subsystem classes via the Get Subsystem node in Blueprints.

The specific pattern is: whichever Blueprint subsystem class I open first in the editor becomes the only one accessible.

For example:

  • If I open BP_A_Subsystem first after engine launch, then in Blueprints, will only return an instance of BP_A_Subsystem_C.
  • Conversely, if I open BP_B_Subsystem first, then only BP_B_Subsystem_C can be searched.

In my specific case, TestGI and Test_Tick are based on different C++ subsystem classes (e.g., one inherits from UGameInstanceSubsystem and the other from FTickableWorldSubsystem, as shown in my screenshot).

Below is my relevant code snippet:

//=====================UBPTickableWorldSubsystem=========================

//BPTickableWorldSubsystem.h

#pragma once

#include "CoreMinimal.h"
#include "Subsystems/WorldSubsystem.h"
#include "BPTickableWorldSubsystem.generated.h"

/**
 * 
 */
UCLASS(Abstract, Blueprintable)
class My_API UBPTickableWorldSubsystem : public UTickableWorldSubsystem
{
	GENERATED_BODY()
	
public:
	virtual void Initialize(FSubsystemCollectionBase& Collection) override;

	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Subsystem", meta = (DisplayName = "Initialize"))
	void ReceiveInitialize();
    
	virtual void Deinitialize() override;

	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Subsystem", meta = (DisplayName = "Deinitialize"))
	void ReceiveDeinitialize();

	// Tickable接口实现
	virtual void Tick(float DeltaTime) override;
	virtual TStatId GetStatId() const override;
	virtual bool IsTickable() const override { return true; }

	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Subsystem", meta = (DisplayName = "Tick"))
	void ReceiveTick(float DeltaTime);
};


//BPTickableWorldSubsystem.cpp

#include "Tool/BPTickableWorldSubsystem.h"

void UBPTickableWorldSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
	Super::Initialize(Collection);
	ReceiveInitialize();
}

void UBPTickableWorldSubsystem::Deinitialize()
{
	ReceiveDeinitialize();
	Super::Deinitialize();
}

void UBPTickableWorldSubsystem::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	ReceiveTick(DeltaTime);
}

TStatId UBPTickableWorldSubsystem::GetStatId() const
{
	RETURN_QUICK_DECLARE_CYCLE_STAT(UBPTickableWorldSubsystem, STATGROUP_Tickables);
}



//=====================UBPGameInstanceSubsystem==========================


//UBPGameInstanceSubsystem.h

#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "BPGameInstanceSubsystem.generated.h"

/**
 * 
 */
UCLASS(Abstract, Blueprintable)
class My_API UBPGameInstanceSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()
	
public:
	virtual void Initialize(FSubsystemCollectionBase& Collection) override;

	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Subsystem", meta = (DisplayName = "Initialize"))
	void ReceiveInitialize();
    
	virtual void Deinitialize() override;

	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "Subsystem", meta = (DisplayName = "Deinitialize"))
	void ReceiveDeinitialize();
};


//BPGameInstanceSubsystem.cpp

#include "Tool/BPGameInstanceSubsystem.h"

void UBPGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
	Super::Initialize(Collection);
	ReceiveInitialize();
}

void UBPGameInstanceSubsystem::Deinitialize()
{
	ReceiveDeinitialize();
	Super::Deinitialize();
}

----------------------------------------:thinking:------------------------------------------------

I recall that in previous versions, Blueprint Subsystems created using the same inheritance method were not directly searchable in Blueprints, but in UE 5.6, it appears that they can now be searched for directly.

This behavior seems to be tied to the editor’s initialization order or subsystem class caching. Any insights into why this happens or how to reliably get the correct Blueprint subclass instance would be greatly appreciated. Thank you! :smiling_face_with_three_hearts:

You are running into issues because currently (even as of 5.7) Subsystems are not designed to be, or are well integrated with, being Blueprintable.

What you are seeing is one consequence of this.

Another is that at runtime, very often the blueprint subsystem will not be created at all. Sometimes in PIE it will seem like it works, but only because of how the Editor needed to load the blueprint or kept the blueprint loaded. Often it will work fine when initially making & testing the subsystem, but then fail when the editor is restarted. And then it will not work at all in a standalone or cooked build because you’ve written no logic to load them.

The loading issue can be a little tricky to fix (depending on the subsystem you’re trying to implement). I hadn’t heard about this Editor UI issue before, but it’s just another strike against the whole thing.

Usually if someone wants a blueprintable, subsystem like thing, they just go with an AActor or AInfo that they spawn themselves. It’s what we did in UE4 before subsystems were a thing. As great as subsystems are, this is one case where it just doesn’t work (for now).

Thank you for your reply.

It’s weird that UE 5.6 already allows direct searching in Blueprints (even with issues), so why doesn’t Epic go a step further and directly expose subsystems to Blueprints?

I’m not sure what you mean. As far as I remember, if you marked a subsystem blueprintable it would show up in the editor as an option to create blueprints. This is why you can find lots of confused posts on the forums and reddit and why I already had a notion about the issue you were running into. Because it’s something we’ve had to talk people down from trying since they were introduced.

I think that the combination of lifetime concepts and the fact that they don’t replicate meant it was less problematic to have them work this way than have to deal with folks not understanding why other (more complicated things) didn’t work for their blueprint.

I get it! Thanks a lot again. :smiling_face_with_three_hearts: