Download

What is the recommended way of referencing Blueprint objects from c++?

I have a custom AI controller c++ class, from inside which I’m trying to load and run a BehaviorTree blueprint. I use the FObjectFinder to load the BehaviorTree object.


const ConstructorHelpers::FObjectFinder<UBehaviorTree> BehaviorTree(TEXT("BehaviorTree'/Game/Enemies/EnemyBehaviorTree.EnemyBehaviorTree_C'"));

While this code compiles without error in Visual Studio and everything works flawlessly in the editor, the editor’s output log actually states that it is unable to find the object. I’ve been using this method to reference Blueprint classes like BehaviorTrees and UMG widgets for a while now, and only realized this first when I tried to package the project with no success. Also, adding ‘_C’ to the end of the path string causes the same error, except running the tree doesn’t work even when played from editor.

That being said, I’d like to ask: What is the proper way of accessing Blueprint objects and classes from c++? I’m aware that creating a TSubclassOf variable in the c++ class and setting it in a derived Blueprint class is an option, but that would mean creating several child Blueprint classes with no functional difference from their c++ parents, which seems to me like a rather clunky solution (or is that the usual UE4 workflow?).

A simple example of spawning a new object instance from a blueprint (or any other type of) Uclass:



UObject* AMySpawner::NewObjectInstance(UObject* Context, UClass* Class) {

    if ( !Context || !Context->IsValidLowLevelFast() || Context->IsPendingKill() ) { return nullptr; }
    if ( Class == nullptr ) { return nullptr; }

    auto World = GEngine->GetWorldFromContextObject ( Context, EGetWorldErrorMode::LogAndReturnNull );
    if ( World != nullptr ) { return NewObject<UObject>( Context , Class ); }

    return nullptr;
}


Or just getting the CDO (class default object) which is always spawned by the engine when game exe is launched:



UObject* AMySpawner::GetClassDefaultObject(UClass* Class) {
    return Class->GetDefaultObject(true);
}


Thanks for the swift reply.
However, my problem is not spawning an object from class, but retrieving the class reference at all (as FClassFinder doesn’t work properly).

TSubclassOf *is *a reference to the UClass.

Indeed, but it can only be set to a Blueprint class reference inside another Blueprint. Is that correct?
Creating a new Blueprint class just to set a reference inside it is what I’ve been trying to avoid, if possible.

If you’re working with native objects, then blueprints are your config files where you set up variables. They should be used similarly to how Unity does prefabs, except they also have the ability to be scripted outside of the native code.

I see. Thank you, that’s exactly what I wanted to know. :slight_smile:

There is another way: you can set your UPROPERTY as a config variable and set the reference to the asset in your config files. There is one problem with this approach compared to using a blueprint class to store the properties: you need to add the asset to your project settings “always package” list because UE4 has no way to know its being referenced by anything and thus that asset will be skipped when you package your game. When you use a blueprint class as a “config repository” all references will be automatically tracked by the engine for packaging.

Your code does not use Class Finder, it is using ObjectFinder these are not the same. Objects dont exist in blueprints, classes do. Objects get created from the classes.

And no, I would not recommend using config files. You would need a different class TYPE for any settings that change. This means its not a setting, its a type.

You cant have a specific spawner for the 12 types being spawned. Instead you want a generic spawner that will work for any type.

Config settings, change every INSTANCE of that variable via the CDO’s value.