Subsystem function call failure

Hi!

I faced an issue working with subsystems.

I have a simple c++ subsystem UMyGameInstanceSubsystemCpp, with one simple function declaration GetMyString:

#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystemCpp.generated.h"

UCLASS(DisplayName = "CppSubsystem", Blueprintable)
class SUBSYSTEMTEST_API UMyGameInstanceSubsystemCpp : public UGameInstanceSubsystem
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "MyCategory")
	FString GetMyString() const;
};

Then I am creating a new Blueprint class BP_MyGameInstanceSubsystem derived from UMyGameInstanceSubsystemCpp, and implementing this single function:

And finally I have one dummy actor BP_DummyActor on scene which calls this function GetMyString on BeginPlay:

It works as intended if I am testing in SelectedViewport or NewEditorWindow(PIE):
image
It prints pre-call message, print message inside subsystem function, prints function return result and then post-call message.

But when I am trying to test in Standalone - it doesn’t work well:
image
It prints pre-call and post-call messages, but function doesn’t get called. Instead it prints default function return value (empty string) and internal print doesn’t get called.

And one more strange thing: it doesn’t work in shipment build of this test project, but works in shipment build of our main project.

Git repository of test project: Git repository

Could anyone help me with this issue? I want to make it work in every case, or to understand that I am doing wrong and why it is impossible.

Thank you!

UPDATE & SOLUTION
TLDR:
The subsystem was not being picked up properly for asset scan. This was solved by going “Project Settings” → “Game” → “Asset Manager”, then adding a new entry to the Primary Asset Types To Scan . Just referencing the asset seemed to do the trick for me.

Full post: Subsystem function call failure - #5 by YB_Wertolet

1 Like

Correct me if I’m wrong, but I don’t believe there’s any way to tell the Subsystem system to use a Blueprint based Subsystem?

You just need to make your c++ class blueprintable, so you can extend it in blueprint.
You can see it in attached project.
It works quite well in our main project, but some functions like one in attached project - are unstable.
Don’t get me wrong, if it works don’t mean it should, but I haven’t found any info that Subsytems can’t be extended in blueprints.

ah, right, i’d forgotten that subsystems are auto instantiated, you don’t have to put them into a config somewhere.

I do remember either reading or seeing in a video that blueprint subsystems weren’t a thing that were supported, however it’s entirely possible that that has changed since then. I’m pretty sure it was in the Epic video training that introduced Subsystems.

I think I would suspect some sort of strange initialization order causing it to work in one project but not in another. That might have you debugging deep into the internals of the engine if you want to really figure it out … you could try calling GetMyString() from somewhere in native code, with a breakpoint on it, debug into what happens, and try and figure out why it doesn’t come up with your blueprint class.

I do also wonder what would happen if you implemented it as a BlueprintNativeEvent, and left a default C++ implementation that perhaps logs something, then tried to call it, and see what happens.

1 Like

The solution to this issue was found by Sebastian Kolbu

First of all UCLASS(Abstract) was added to prevent the C++ implementation from being instantiated.
The subsystem was not being picked up properly for asset scan. This was solved by going “Project Settings” → “Game” → “Asset Manager”, then adding a new entry to the Primary Asset Types To Scan . Just referencing the asset seemed to do the trick for me.

Exactly what subsystem instance we got prior to this, I don’t know. For some reason it would be a valid object to operate on, yet the methods returned nothing (even after locally changing the C++ GetMyString to default implementation return TEXT("C++")).

FString UMyGameInstanceSubsystemCpp::GetMyString_Implementation() const
{
	return TEXT("C++");
}

In the screenshot (Standalone) you can see that I am printing two things: BP and C++. This is done by explicitly getting the BP version of the Subsystem, as well as the C++ version. If set up properly, since the C++ version is abstract, it will return the BP version (which should be the only instantiated one). So now regardless of which type I am trying to get, I am given the BP


image