At runtime, create instance of BP inherited from a C++ AActor class.

Hi Folks, I know this has been asked before but for some reason I am getting lost in the weeds and confused by many different posts and what not, so I was hoping to get some direct help.

Overall what I am trying to do is have little debug markers. I’ve used debug spheres and they work fine, but, I need more than just that. I also need a widget spawned at the same location to that can give me some debug information at an exact location.

I’ve created a C++ AActor class. For the lack of a better name, AMarker. From C++ at runtime this will get spawned and placed at a specific location. AMarker has two components:
• USPhereComponent
• UWidgetComponent
Further, I made a BP_Marker blueprint from AMarker. I created the blueprint so I could easily assign the static mesh and assign a widget class.

The widget will accept various debug information and display it. I started with a C++ UUserWidget class, and then created a widget blueprint that I will be assigned to the UWidgetComponent variable in the AMarker class.
The widget contains multiple UTextBlock objects to display the debug data. I wanted to use a widget blueprint to make use of the designer to lay the text blocks out.

So basically I have a nice and tidy blueprint that has everything in it and setup the way I want it to display. At runtime, from C++ a controlling C++ class I want to create an instance of my blueprint BP_Marker. I want to also specify that I am not dragging this into the scene, so I need to be able to locate the blueprint itself and spawn it.

Any help will be greatly appreciated!!!

Thanks so much!

What you are looking for is:

TSubclassOf<BP_MarkerBaseClass> PointerToYourBP_Marker;

Declare this somewere in a C++ baseclass that has a BP child class. Then in the editor, you can assign that pointer to your BP_Marker blueprint type.

Thanks Rejji.

I’m a little confused though… I’m not sure if your solution will work for what I need…

The class that will be instantiating instance of my BP_Marker class is not a blueprint type class, it’s C++ only.

AMyClass is a C++ class only, no blueprint blueprint wrapper at all…

it will have a for loop and inside that for loop I need to instantiate an instance of the BP_Marker blueprint for each iteration.

There will not be any way for me to use a blueprint to specify in the editor what to use.

This might help. Here’s a code snippet that spawns a HUD blueprint in C++ code and adds it to viewport. This is functionally equivalent to adding the HUD blueprint via the level blueprint.

// in your .h file
UPROPERTY()
	UPrimaryToolbarHUDWidget* _toolbarHudWidget = nullptr;

void LoadBlueprint_PrimaryToolbar();

// in your .ccp file
void APrimaryHUD::LoadBlueprint_PrimaryToolbar()
{
	// load the HUD bluprint and add to viewport
	// note: '_C' must be appended to the BP name, why? because Unreal ...
	FSoftClassPath toolbarClassReference(TEXT("/Game/Blueprints/HUD/PrimaryToolbar.PrimaryToolbar_C")); // append "_C"
	UClass* toolbarClass = toolbarClassReference.TryLoadClass<UUserWidget>();
	if (toolbarClass != nullptr)
	{
		// loaded the blueprint, save reference, and add it to the viewport
		UUserWidget* userWidget = CreateWidget<UUserWidget>(GetWorld(), toolbarClass);
		_toolbarHudWidget = Cast<UPrimaryToolbarHUDWidget>(userWidget);
		if (_toolbarHudWidget != nullptr)
		{
			_toolbarHudWidget->AddToViewport();
		}
	}
}

It is very useful to have BP child classes for C++ classes for this reason. It gives you access to both levels.

If you have no instance of this setup, then make one, and reference it throughout your project so that you can reference BP instances.

The code sample given above is good, but it is best practice to avoid hard coded text references into BP.

Don’t do this. Add a soft pointer property to your HUD or as a parameter to your “LoadPrimaryToolbar” method which you set up from your blueprint asset deriving from this HUD. It avoids the hardcoding and lets you set up variants with ease.

All about Soft and Weak pointers | Tutorial

You can’t avoid blueprints with widget because widgets are designed in blueprint assets. There’s also the “BindWidget(Optional)” flag to be used in c++ UserWidgets you can use to further improve your experience here.

Connect C++ to UMG Blueprints with BindWidget · ben🌱ui

Same idea, write as much logic as possible in c++, from blueprints pass in a soft pointer to your blueprint asset BP_Marker to your c++ method to spawn it. Don’t try to hardcode / find blueprint assets from the c++ side.

A quick copypasta of spawn code from soft ptr:

UWorld* WorldX = ThisActor->GetWorld();
const TSubclassOf<AMyActor> AnActorClass = MySoftPtrActorClass.LoadSynchronous();
if (IsValid(AnActorClass)) {
	AMyActor* NewActor = WorldX->SpawnActorDeferred<AMyActor>(AnActorClass, SpawnTransform, ThisActor, ThisActor->GetInstigator(), ESpawnActorCollisionHandlingMethod::AlwaysSpawn);
	check(IsValid(NewActor));
	NewActor->FinishSpawning(SpawnTransform);
}

Add a soft pointer property to your HUD or as a parameter to your “LoadPrimaryToolbar” method which you set up from your blueprint asset deriving from this HUD. It avoids the hardcoding and lets you set up variants with ease.

Hmmm, so how would that code change to dynamically load a HUD blueprint via C++ given a string location path of the HUD blueprint only? The goal is zero setup in levels or blueprints to dynamically load any HUD.

TBH the string path has never been an issue though. Major HUD elements rarely change location and its a simple string change if it does. The logging (which I omitted) catches any invalid paths.

C++ string paths are/were also generally frowned upon because they prevent cooker from detecting dependencies, which results in dependent classes not being packaged in shipping build, then you get nullptr when using TryLoadClass or StaticLoadObject or the likes.

At least that used to be the case.

Nowadays afaik you can use the static FClassFinder pattern in constructor which should take care of notifying the cooker about dependencies.

Not sure about packaging issues nowadays with other methods of dynamic loading, but in any case you can also force-include directories to cook in project packaging settings.

Also you might want to consider using a Config FSoftClassPath variable, then set your path in ini file. It’s easier to change ini than having to recompile. Engine does it all over the place.

Thanks for the reply… I ended up going a different route. I created a delegate that pushed data from C++ up to blueprint. A delegate that could be subscribed to by blueprint…

But, I still want to figure out the proper way to do this…

Do you know of any examples? Tutorials on how to do this using the methods you described?