How to get a UClass Reference in C++ outside the constructor

How would I go about getting a reference to a UClass of a blueprint class in C++ if I’m outside of the constructor and not able to use the Constructor helpers.

I found this old posting: Get Blueprint class by String in C++ - Programming & Scripting - Unreal Engine Forums

But I just can’t find the proper string to use as the class name itself when trying to use this. I just can’t figure out the logic behind the naming conventions.

if you have a reference to the blueprint, you can just use the “GeneratedClass” member which gives you the correct UClass.
Is there any reason why you need to construct a UClass from a string?

Well, I just need a class reference in some C++ code because I’m working on code that’s too complicated to write in blueprint. I have a lot of C++ and Blueprint interop going on.

It’s kindof the same reason, when you create a shooter game in C++, GameMode retrieves the blueprint pawn class:


static ConstructorHelpers::FClassFinder<APawn> PlayerPawnClassFinder(TEXT("/Game/Blueprints/MyCharacter"));
DefaultPawnClass = PlayerPawnClassFinder.Class;

Only I want to do this outside the constructor.

Rather than constructing from a string, I create a variable on the actor:


UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Blueprints")
class UBlueprint* TheObjectBlueprint;

And then anywhere in code I do the following:


if (TheObjectBlueprint)
    UClass* ClassRef = TheObjectBlueprint->GeneratedClass

Which gives me a reference to the desired class without messing around with any strings.

Hopefully that helps.

EDIT:
Just realized you were only after the class.
If that’s the case you can do the following:


UPROPERTY(EditAnywhere, BlueprintReadOnly, noclear, Category="Class Types")
TSubclassOf<class UBaseObjectType> LookupClass;

Which will give you a drop-down of valid classes (Including blueprint types.) Which you can then use directly.

3 Likes

That’s what I’m doing now since I have no other way to do it. I initialize the class reference from the C++ constructor, or I can create the class reference in Blueprint itself in the editor.

This adds a bit of tediousness to the thing I’m trying to do in this case since I now have to have all these properties instead of just sitting down and writing some code. It’s basically something that’s too complex for me to do in Blueprint right now. Ideally I’d be doing this in blueprint, but in order to get my game out the door, I decided to keep things simpler and do it in C++ since I don’t have to find ways to expose functions and come up with other complex design decisions. I’m the sole programmer so I don’t have artists who can’t do C++ on my team right now.

As you seem to be adamant on using hardcoded strings, you can do what they were doing in the Answer Hub answer:


FindObject<UClass>(ClassPackage, ClassName)

Where if your blueprint is named: ‘BP_MyBlueprint’
The ClassPackage is the Blueprint name (i.e. ‘BP_MyBlueprint’)
and the ClassName would be ‘BP_MyBlueprint_C’

All blueprint classes have the ‘_C’ appended.

Again, I would recommend actually using the TSubclassOf method, as you really are fighting how the engine works.

Do I need to use the full name of the blueprint? Most things aren’t just named with the display name you see in the editor. There is usually a whole path. I can try these combinations some more when I get home.

I usually use TSubclassOf to store class references themselves. What did you mean by I’m fighting how the engine works? I thought this is normally perfectly fine since you can get class references in constructors. I just wanted to do it outside of a constructor.

To use another coding example, it’s like using magic numbers in code.
Yes it works in practice, but is quite nasty and frowned upon.

This is the same, hardcoded strings to get the class references is more nasty and inflexible compared to having a reference set on a blueprint.
I say your fighting the engine, because you’re trying to work around the issue instead of using it the way it’s designed.

It makes me cringe as a coder. XD

And it is most likely the full path for the package name.
It’s probably something like: ‘/Game/Blueprints/BP_MyBlueprint’

Well, what I’m basically doing is scripting something for a very specific level in my random level generator. Normally, something scripted for a very specific level would be done in blueprint, but my level generator is still in an early stage where I can’t really do low level stuff with it in blueprint. It’s all in C++.

I have a lot of things in my random level generator configurable through blueprint with UPROPERTY and other things. And I have these objects called PostPassEvent objects that let me do some really level specific custom behavior that can’t be done as easily with the generic system I have in place. This is used for puzzles and other very specific things that only that one level will require. My blueprint object has a class reference to a PostPassEvent object. This PostPassEvent object is actually doing some custom behavior in C++ though.

So, for example, on level 2 I need to spawn a locked door from an area that is farthest away from the starting area in my area graph, and then spawn a key that is somewhere else. This should be done in blueprint, but I haven’t exposed blueprint event methods for this kind of thing, so my scripted events have to be done in C++ for now.

Spawning a locked door an key puzzle can potentially be generic enough to be reusable all over the place, but a very specific example is on level 1, traversing my area graph and making all areas branching off of the shortest path between the start and exit have locked doors until a certain objective is completed. This will allow players to quickly get to the main objective in a linear level, and then suddenly the game becomes nonlinear and lets them backtrack and explore once they are no longer noobs and have completed their first basic objective.

Doing this in C++ and not blueprint isn’t the best, but it works and lets me get the game out. I have to cut corners in just the right places or else I’ll be stuck working on this game for years.

Believe me, I care about writing high quality code :slight_smile:

Still no working answer to the problem

FacePalm.exe posted the correct solution IMO, post #4.

I know this is an old post but in researching this issue I haven’t found what is really the answer to this question. Here is what I found to work:

What exactly is the use case? Might be able to help since we do a lot of this stuff outside constructors.

If you are just looking for a specific type of actor during or after BeginPlay() you can always just search for it with ActorIterator:



 // iterate through all world actors
 for (TActorIterator<AInteractiveActor> ActorItr(GetWorld()); ActorItr; ++ActorItr)
 {
   AInteractiveActor* actor = Cast<AInteractiveActor>(*ActorItr);
   if (actor)
   {
       // do something with the interactive actor
   }
}


Oh wow this is kinda old, I actually figured this out a while ago. Here’s a sample code snippet.


TSubclassOf<(C++ Base Class goes here)> SomeBlueprintClass = LoadClass<(C++ Base Class goes here)>(nullptr, TEXT((BluePrintReferenceNameGoesHere)));

An easy way to obtain the blueprint reference name is to right click on the blueprint in the editor, and copy reference.
Then paste it and you get some text. You add _C to the end for some reason, probably C for Class. And it works. Not sure why this wasn’t documented better.

A specific example.


TSubclassOf<UGameplayAbility> SomeBlueprintClass = LoadClass<UGameplayAbility>(nullptr, TEXT("GameplayAbilityBlueprint'/ShooterFramework/Gameplay/Inventory/EquippableAbilities/BP_CH_SFEquippableAbility_EquipDefault.BP_CH_SFEquippableAbility_EquipDefault_C'"))

This is for getting a class reference to a blueprint object outside of the C++ constructor for a UObject where you have constructor helpers.

If you attempt to do the


LoadClass 

method and it’s an asset not in a level you will need to add it to the


DirectoriesToAlwaysCook 

setting in the project to make sure the assets are included in cooked builds.