Download

How do I create an array of unspawned objecs?

I have a world editor that I’m putting together for players to be able to create their own locations in my game. That means allowing the player to spawn any AGameTile through a list in my UI.
This is where I’d like to improve my own quality of living, lol

At the moment, I’ve had to create a UPROPERTY of TArray<TSubclassOf<AGameTile>>, and manually add any tile that I create to the UPROPERTY, and populate my UI using that.

What I really want to do though, just to eliminate one room for error, is to have my UI do something similar to SelectAllActorsOfClass() at the beginning, and then populate a struct using each member. This might seem minute and trivial, but this way I can (for instance) produce 50 tiles and have my code handle the entire process from there, without “Was there one in the middle I forgot? Oh dammit, now which one of the 75 tiles did I miss???”

Problem is that everything I’ve found regarding the selecting of multiple actors, or actors of a given type, only applies to spawned actors.

Am I using the only method available to achieve the result I want? Surely there’s a method of some sort that I’ve just not been able to stumble across?

Thank you in advance for your help.

So I am guessing you have a number of blueprints with a parent class of AGameTile in a folder and you want to be able to reference and spawn those actors as requested without having to fill a list of classes manually.

I have managed to do something similar, but there are quite a few steps I had to take to make it happen.

Firstly I had to create an asset library of the folders I wanted to be able to reference. This is required to be able to access the data within the folders.


UObjectLibrary *pGameAssetLibrary = UObjectLibrary::CreateLibrary(AActor::StaticClass(), true, GIsEditor);
pGameAssetLibrary->AddToRoot();

TArray<FString> assetPaths;
assetPaths.Add(TEXT("/Game/MyAssets1"));
assetPaths.Add(TEXT("/Game/MyAssets2"));

pGameAssetLibrary->LoadAssetDataFromPaths(assetPaths);


From here you can query the asset data



TArray<FAssetData> AssetDatas;
pGameAssetLibrary->GetAssetDataList(AssetDatas);

for (int32 i = 0; i < AssetDatas.Num(); ++i)
{
	FAssetData &AssetData = AssetDatas*;
	// Print off the assets path so we can see what will be referenceable
	UE_LOG(LogSomething, Log, TEXT("Asset Path: %s"), *AssetData.ObjectPath.ToString());
}

You can now synchronously or a-synchronously load this data in to be used.
a-sync is a bit more work using a FStreamableManager. See here: https://wiki.unrealengine.com/TAssetPtr_and_Asynchronous_Asset_Loading
Sync is easy with just a call to AssetData.GetAsset()

Now if this asset is a blueprint and you want to spawn it, a couple more things to do:


UBlueprint *theBPObj = Cast<UBlueprint>(AssetData.GetAsset());
if (!theBPObj || !theBPObj->GeneratedClass)
	return;

AActor *worldItem = GetWorld()->SpawnActor(theBPObj->GeneratedClass);
if (!worldItem || !worldItem->IsA(AGameTile::StaticClass()))
	return;

AGameTile *pGameTile = Cast<AGameTile>(worldItem);

You can store off the FAssetData structures in a map for later and spawn them when you need them.

Hope this helped

Cheers

I’ve seen questions like this asked a lot, so since I’m setting up a new website it seems like a good topic for a first article. I’ll post a link here when done, but it’ll be a couple of days at least.

In the meantime, the short answer is you need to use the asset registry. There’s an example here doing something similar, but that code is only safe to use in editor-only code, it won’t work at runtime.

Thank you both for taking the time to answer! Rfsheffer, I definitely appreciate the coding example–I’ll be looking into asset libraries and asset registries (these are totally foreign to me) and try using your example code.

Kamrann, I’ll take a look at your code too, but can you explain why rfsheffer’s code would only be usable in the editor.?

I was actually referring to the code I linked, but the last part rfsheffer’s code also has the same issue - blueprints don’t exist in a packaged build. Only the generated classes get packaged, so attempting to get a pointer to a UBlueprint in a packaged build will always fail.

That said, rfsheffer’s code using UObjectLibrary might be workable using classes rather than blueprints, I’m not sure as I haven’t used that class myself.

Starting to sound to me like my uproperty of subclass tarray might be the best way…

Thanks kamrann for the concern, I will see if my package build isn’t proper because it is working for me. One thing to note about my project though is I included the asset folders in the “Additional Asset Directories to Cook” list so they would be forced into the package. That might be the reason it works? Our project also includes “UnrealEd” as a dependency module which I was hoping to strip out.

Article on doing this now available here.

@rfsheffer: Yeah, you won’t even be able to package your project with a dependency on UnrealEd, you’ll have to remove the dependency or restrict it to editor builds.

So I guess the solution is to have an unreal object grab all of the references in the folder and be serialized to a file. Then I can load that UObject and get all the references that way.