How do I load a blueprint in C++?

There are a lot of similar question, I know, but almost all of them revert to having to select the blueprint in the editor as a property of the C++ class. This is not going to work for me. I am trying to write a factory class that allows me to spawn actors by ID at runtime, essentially procedurally generated.

I have tried using a ConstructorHelpers:FObjectFinder but this doesn’t work. But then calling StaticLoadObject() doesn’t work either.

Here is my current code. It is a bit more verbose than usual to allow me to explore what is happening.

UObject *obj_ptr = StaticLoadObject(UObject::StaticClass(), NULL, TEXT("/Blueprint'/Game/Props/LitTorch.LitTorch'"));

The resulting pointer is null. I get this error: LogUObjectGlobals: Warning: Failed to find object ‘Object /Game/Props/SM_LitTorch.SM_LitTorch’

I also tried using the string Blueprint'/Game/Props/LitTorch' but then got an error at compile time about not being able to find the package.

This is the common advice because it’s the best practice for configuring these types of content references. Constructor helpers are bad for real projects and have many, many, many downsides and zero upsides. They are used in the templates for reasons that aren’t applicable to “real” projects.

It is also significantly less error prone (as you’re finding with the paths) to select them using the Editor UI and allows non-coders to configure things.

A half step if you just want a place to create an association between IDs and blueprints would be a UDeveloperSettings class that would automatically have it’s properties show up in the Project Settings of the Editor.

However, if I were building this sort of system I would do this (I’m going to throw a lot of engine names around so you have search terms or can ask specific questions):

  1. Create a primary data asset type to represent a piece of content (let’s say, UPCG_PDA). This would have a reference to the blueprint to spawn (as a soft reference), maybe an ID (though this plan wouldn’t require it) and any additional simple meta data about the actor you might use for deciding to spawn it (size, type, etc)
  2. At some point (main menu, game start, etc) you’d load all the instances of UPCG_PDA’s that exist in your content. This shouldn’t be a problem since the blueprint would be a soft reference and the data asset itself would be very small.
  3. After loading them, you could preprocess them to create a mapping by ID or types or whatever you want in order to look them up.
  4. At some point you load the blueprint from the soft reference on the pda. Maybe this is during generation. Maybe you have enough metadata to do the generation entirely using the pda and only load the blueprints after you finish the generation and know what blueprints to load.

The additional benefit to this (or even the DeveloperSettings approach) is that as you make new content, you don’t require a recompile to update your references. And you don’t open yourself up for the sorts of terrible things that ConstructorHelpers have been known to do to projects.

Again, the reason that you’re seeing that as the consistent advice is because it really is the best way to do it and the pattern to get comfortable with from the start of development.

Umm. So if I have a hundred blueprint actors, then I need a hundred C++ classes and then need to manually, in the editor, select the correct blueprint for each C++ class in turn.

No thanks.

Also, I am not proposing using constructor helpers. I am proposing using StaticLoadObject(). Forgive my ignorance if that is basically the same thing.

What I want to be able to do is something like this:

namespace {
    const std::vector<const char *>  ASSETS =
    {
        "/Blueprint'/Game/Props/LitTorch.LitTorch'",
        "StaticMesh'/Game/Props/Chair",
etc. etc.
    };
}

void ObjectFactory::Initialise()
{
    for (uint16_t i = 0u; i < ASSETS.size(); ++i)
    {
        UObject *object = LoadTheDamnAssetByItspath(ASSETS[i]);

        m_assets.emplace(i, object);
    }
}


AActor *ObjectFactory::CreateAsset(uint16_t id, const FVector &position, const FRotator &rotation)
{
    AActor *result = nullptr;
    auto    it     = m_assets.find(id);

    if (m_assets.end() == it)
    {
        UE_LOG(LogTemp, Warning, TEXT("Object type %u not known by factory."), id);
    }
    else
    {
        result = m_world->SpawnActor<AActor>(.... etc. etc. ...);
    }

    return result;
}        

To add an asset to my factory now takes 1 line of code. Not a whole new class and a load of clicking around in the editor.

I am really new. This whole explanation went right over my head. What is UPCG_PDA?

MagForceSeven:

you don’t require a recompile to update your references.

I am a C++ engineer. My work pattern is code→compile→test→code→compile→test. I am working on a fully procedural game. My map is literally empty. I have to have a map so I call it “empty” and the file is “empty.umap”. I only use the editor to play around and see how things look, or mess about with materials and particle effects. So I am completely happy to recompile every time I make a change.

The only reason I want to use a blueprint is I don’t know any other way to combine a static mesh and a particle effect within a single asset. Currently my object factory has to manually detect specific asset IDs and manually attach the particle effect to the static mesh. And then detect the asset when destroying it and deactivate the particle effect. it is a pain.

So I just saw this text on the internet: “The CompileAllBlueprints commandlet allows you to recompile all Blueprint assets in your project from the command line”.

I am using RunUBT.sh and RunUAT.sh to build my project. At no point do I use that “commandlet”. The example I was following did not mention it at all. Should I be? My build steps are:

RunUBT.sh MyGame Linux DebugGame -Project=my_game.uproject
RunUAt.sh BuildCookRun -project=my_game.uproject -targetplatform=Linux -pak -package -stage -cook -clientconfig=DebugGame

If I put a bad path to StaticLoadObject() then this build fails, which is a bit weird. But the lack of that error seems to suggest that the reference is valid in some way.

Not at all, you only need to have 1 class that has all the configuration data. You don’t need a unique one for every blueprint. With the thing I was proposing you’d have two assets for every pcg thing, not a unique class per pcg thing.

Fair enough. However most of the downsides are true for any hardcoding of asset paths in the manner that you are proposing.

So am I, so I understand that. However there are things that you shouldn’t have to restart the editor for, like adding new elements to your PCG set. Changing the algorithm, sure. But adding chair #6 that’s similar to the other ones, it’s just a waste of time. You’re probably working alone, but maybe someday you wanna work with someone else, maybe an artist to make nicer pcg elements than you can. They’re not going to be going to editing code.
My primary hobby project is also an empty map because it’s a tactics game and procedurally add elements to the map. So I really, really do get it.

That was just a made up type so that I could refer back to “a procedurally generated content primary data asset” by short hand.

That’s okay. I’m happy to explain or link to things for specific questions if you don’t find them on your own. Likely any alternative will have a learning curve if you’re new and that’s not a bad thing.
Alternatively there’s a thing in the engine called the Asset Registry. It’s possible that if you organized all your content in a reasonable way, you could ask it for the list of all the blueprints in a particular content directory (or directories) to build that list instead of hardcoding it.

No. That’s just an automated way to compile blueprints the way they are in the Editor to check for errors. Teams will use it on automated build machines to validate that blueprints still compile after someone checks a change into source control.

I guess you’re running UBT manually because Linux doesn’t have a reasonable IDE with Unreal Integration?
I think that you’re way to early in your process to be building and running cooked builds. You should build DebugGameEditor and run that. If you want to test it running, just use the Play In Editor (PIE) that is almost always good enough.

The lack of an error is because you’ve hardcoded a path and the cook doesn’t/can’t/won’t inspect any code. It’s strictly an asset processing tool. And you won’t get any errors from the compile because it only deals in code and knows nothing about assets. So your build fails with a runtime issue because that’s the earliest it can be known. This is one reason (among many) why hardcoding asset paths is discouraged.
It’s also possible (I don’t know how you have your project cook settings set up) that the cook is skipping all your pcg blueprints because nothing that it would cook is referencing them. Admittedly that’s kinda the whole point, I get that. But references from code won’t cause assets to be included in the cook.
In the plan I suggested with the primary data asset, that asset would be something that always cooks and because it would reference the blueprint for the actual content, the blueprint would get cooked. Also you would get errors during the cook (or even blueprint compile I think) if you had a reference from one of those assets to a blueprint that no longer exists.
But if you went with the Asset Registry solution, there are ways to make sure that content is cooked without being referenced.

Listen, the engine really is designed to use both Blueprint and C++ in concert with each other. If you fight that, you’re just going to cause yourself unneeded frustration. If you want to use a hammer with screws, that’s fine but you’re not going to get much useful help. You’re going to get (and find) lots of “use a screwdriver with screws”. Not understanding how to use a screwdriver doesn’t make it any less the right tool. This forum (or the Unreal Slackers discord) want to help you understand it.

What about having a struct that contains an array of soft pointers. Then you can add the assets in the editor and use them in C++ by just using LoadSynchronous()?

You can pass in a different struct for each level to your factory.

If you want to keep it all in C++, I’m sure you can create soft pointers with the asset path.

@MagForceSeven:

Thanks for that lengthy explanation. I’ll go through it later. One thing that confused me is “PCG” which seems to be your acronym for Procedurally Generated Content (PGC).

I think your suggestion seems to be to have a sort of asset registry class (my object factory) and then add a property to that for each asset. Is that right?

The asset registry also seems like a good idea. I will look into that later.

One consideration is that IDs (or indexes) cannot change, so if ID 4 is a chair, it needs to always be that chair even if someone adds an “abacus” asset, for example. As I understand it, the editor setting of a specific asset into a specific slot gets saved to a file under Configuration, is that right? So if someone fiddled with the setting then a code review diff would show that.

When you originally said this I didn’t notice the “engine names” at all. I had a closer look and now I can see them. Thanks for that, but quotes would have helped.

So having read about data assets and primary data assets, why would you use a primary data asset rather than a normal one? The example given for a data asset is an array of static meshes which seems exactly what I need.

Wouldn’t I just need one? With an array of assets inside it? This is where my earlier confusion came from, thinking I would need hundreds.

I don’t have an ID, but that’s just me. I got fed up with IDEs ages ago. There are so many of them and different projects want you to learn different IDEs and it’s a pain, so I just use gVim and a bunch of command line tools for all my programming these days. I hand-write Qt layouts and manually edit Visual Studio and Keil project files and all of that.

I use UBT and UAT because I am using CMake. I can get that to run in a CI system as well as in my development process. Not so much if I am using an IDE.

I know you say construction helpers are a bad idea, and I get that, but it should work, right? I would quite like to get that working to be sure I am loading things correctly. Or is that all just a waste of time?

Not my acronym, the engine’s acronym for the systems it already provides for doing Procedural Content Generation. Overview docs here

That was one of the suggestions yes.

Yeah, IDs are tricky. Using index into an array is really only a good idea for things in a single execution. They are brittle to changes made to content or code. Even your example code would easily break if someone inserted a new blueprint path instead of adding to the end. And you end up with a very disorganized list.
But you could use the path, or an ID property on the asset.

Generally asset settings are saved in the uasset file, not into files in Config. You can do that by marking up specific class properties as Config, but it’s not the default behavior.

Great question! There are a few reasons to prefer them in this case.

First is that they are very easy to enumerate (get a complete list of) at runtime. This makes it very easy to write systems that don’t care about the details of the content (like a hardcoded list) and just try to work with the pile of content that it finds. In a team this means that it’s very easy for non-coders to add more content to the game. And as I hope you find out, also makes it easier for you to add more content faster (since you don’t have to restart to test any of it).

Second is that it provides a very easy way to include the content in a packaged or cooked build. The cook starts with a known set of assets, recursively gathers up all their dependencies and cooks them. When you setup a new primary data asset type it’s very easy to configure the type to ‘Always Cook’ and you can not worry about it. There are alternatives to this, you can set up content directories that should “always cook”, but that is open to human error if they put something where it shouldn’t be or you want to reorganize your content layout.

Thirdly, they provide easy ways to load the secondary assets (textures, blueprints, meshes, etc) that the asset references using “asset bundles”. This is functionality that allows you to markup properties as being part of one or more “bundles” so that you can load “all the content needed for UI” without having to write code that loads individual members of the class.

Oh! They also have an existing ID system that you could use instead of trying to manage your own! Not why I would use a PDA, but in your case a boon!

You could do that. You could also do multiples, but not one per asset (something like one for all chairs, one for wall sections, one for traps, etc).
But with what I was proposing the PDA was acting a more than just a reference to the asset but also as metadata about the asset. Things you want to know about the asset without having to actually load it. It could have variant information, so two PDA reference the same blueprint asset but after spawning it you use some info from the PDA like a color or material reference to make the chair blue instead of green.
Or let’s say you want an in-game editor for debugging or to be player facing. The PDA could have a display name and short description to populate the UI and show all the hundreds of choices without having to load any of the blueprints until you actually want to place one.

Yes … you’ll possibly have another asset for every one of the blueprints you make as a PCG element. But I think you underestimate the number of assets each element will likely already involve that adding one more isn’t a big hurdle. It’s not like you’re making them en-masse. You’re making one at the same time you’re making one new blueprint.

Of course there’s also the built-in PCG systems the engine provides that I don’t have any direct experience with. Setting up content to leverage that instead would probably have entirely different set of advice from someone.

Sure it should, if you get the paths right and a few other things. But yeah, I think it’s a waste of time trying to get those things working when you can more easily set up hard or soft reference properties, fill them in in the Editor and either have them be loaded already (hard reference on somthing you load) or calling LoadSynchronous on a soft ptr.