Dynamic blueprints loading

Hello, I wrote a func that finds an asset(blueprint in my case) by name, loads it and returns it like TSubcalssOf. It really usefull for spawning object in blueprints.

TSubclassOf<AShip> UShipUtils::GetShip(const FString & name)
{
	auto ships = GetAvailableShips();
	if (ships.Find(name) != INDEX_NONE)	{
		TArray<FAssetData> Assets;
		auto lib = LibraryManager::GetLibrary("ships");
		lib->GetAssetDataList(Assets);
		for (int32 i = 0; i < Assets.Num(); ++i) {
			FAssetData& assetData = Assets[i];
			if (assetData.AssetName.ToString() == name) {
				GEngine->AddOnScreenDebugMessage(-1,5.f,FColor::Green,TEXT("AssetFound - "));
				assetData.GetAsset();
				UBlueprint * bp = Cast<UBlueprint>(assetData.ToStringReference().ResolveObject());
				if (bp) {
					GEngine->AddOnScreenDebugMessage(-1,5.f,FColor::Green,TEXT("cast done"));
					if (bp->GeneratedClass->IsChildOf(AShip::StaticClass())) {
						return *(bp->GeneratedClass);
					} else {
						GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Class isn`t cild of AShip"));
					}
				} else {
					GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("cast FAILED));
				}
			}
		}
	}
	return NULL;
}

That code works perfectly in editor, and even if i press Play->Standalone. But if I press Launch, something goes wrong…

There what i find out:

assetData.GetAsset();

returns null if I Launch the game but works fine in standalone mode. So i replace it with StaticLoadObject
And my code now looks like that

//assetData.GetAsset();
				auto obj = StaticLoadObject(UObject::StaticClass(), nullptr, *assetData.ToStringReference().ToString());
				if (!obj)
					GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Failed to load object"));
				UBlueprint * bp = Cast<UBlueprint>(obj);

And it still works fine in editor and standalone, and it even loads the object(obj != NULL) when i launch the game. But only when i launch the game it can`t cast my obj to UBlueprint. What can I do about it?

1 Like

In logs i find that:
[2014.08.27-06.25.07:341][571]LogUObjectGlobals:Warning: Failed to find object ‘Object /Game/blueprints/ships/FirstShip.FirstShip’
Where ‘/Game/blueprints/ships/FirstShip.FirstShip’ is blueprint that i am trying to load. And it exsists.

Hey there,

I imagine your issue here could be due to the object/package not being cooked as it will not be referenced by the level or anything else which is being cooked.

What you’ll need to do is make sure the cooker knows it needs to do this. You can see information on that here.
https://answers.unrealengine.com/questions/49043/cooking-unreferenced-assets.html

See if that solves your issue.

Function which works in standalone, PIE and shipped game.

bool UMyBlueprintFunctionLibrary::ListAllBlueprintsInPath(FName Path, TArray<UClass*>& Result, UClass* Class)
{	
	auto Library = UObjectLibrary::CreateLibrary(Class, true, GIsEditor);
	Library->LoadBlueprintAssetDataFromPath(Path.ToString());

	TArray<FAssetData> Assets;
	Library->GetAssetDataList(Assets);

	for (auto& Asset : Assets)
	{		
		UBlueprint* bp = Cast<UBlueprint>(Asset.GetAsset());
		if (bp)
		{
			auto gc = bp->GeneratedClass;
			if (gc) 
			{
				Result.Add(gc);
			}
		}
		else 
		{			
			auto GeneratedClassName = (Asset.AssetName.ToString() + "_C");			

			UClass* Clazz = FindObject<UClass>(Asset.GetPackage(), *GeneratedClassName);
			if (Clazz)
			{				
				Result.Add(Clazz);
			} 
			else
			{
				UObjectRedirector* RenamedClassRedirector = FindObject<UObjectRedirector>(Asset.GetPackage(), *GeneratedClassName);
				if (RenamedClassRedirector)
				{
					Result.Add(CastChecked<UClass>(RenamedClassRedirector->DestinationObject));
				}
			}			
			
		}
	}

	return true;
}

2 Likes

Hello,
I’m trying to use your code to get all UserWidget in one of my folders.
The list returned is always empty, do you know how I could do it?

Thank you,
Dex

Any chance you can make this in to a blueprint c++ class? Showing the .h and .cpp needed? Its a great plugin!