GetAssetByObjectPath Won't work for Blueprint in packaged builds

(UE 5.2) If you use FAssetRegistryModule::GetAssetByObjectPath() to get a Blueprint asset, it works on the editor but not on packaged builds. This happens with C++ or the Blueprint version of the same code.

PS: The Blueprint is being properly packaged, its functions are available and being used elsewhere.

Is this the expected behavior? Am I missing something? Can someone please clarify if this is by design or if any specific setup is needed?

To reproduce it

  1. Create a new C++ project
  2. Create any Blueprint asset
  3. Create a C++ class and add a function to trigger the code
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::White, TEXT("Function run"));

const FAssetRegistryModule& AssetRegistryModule{ FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry") };

const FAssetData AssetData{ AssetRegistryModule.Get().GetAssetByObjectPath(FSoftObjectPath("/Script/Engine.Blueprint'/Game/TestBP.TestBP'")) };

if (AssetData.GetAsset())
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::White, TEXT("Asset found"));
  1. Call the function somewhere
  2. Test on the editor and watch it work
  3. Package and test. Watch it fail.

Edit: Ok I did a full loop of assets and filtered by name:

	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::White, TEXT("Function run"));

	const FAssetRegistryModule& AssetRegistryModule{ FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry") };

	//const FAssetData AssetData{ AssetRegistryModule.Get().GetAssetByObjectPath(FSoftObjectPath("/Script/Engine.Blueprint'/Game/TestBP.TestBP'")) };
	const FAssetData AssetData{ AssetRegistryModule.Get().GetAssetByObjectPath(FSoftObjectPath("/Script/Engine.Blueprint'/Game/TestBP.TestBP'")) };

	TArray<FAssetData> AssetData2;
	AssetRegistryModule.Get().GetAllAssets(AssetData2,false);

	if (AssetData.GetAsset())
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::White, TEXT("Asset found"));

	for (int32 i = 0; i < AssetData2.Num(); i++) {
		{
			if (AssetData2[i].GetAsset()) {
				FString n=  AssetData2[i].GetFullName();
				if (n.Contains("TestBP")) {
					GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::White, "Asset found: " + n);
				}
			}
		}
	}

This is what showed up:
bp

The loop works and finds the correct asset but can be rather slow.

1 Like

Thank very much! Your first answer were also correct. The asset is not found in the path because Blueprints receive a different treat after packaged.

I was able to work around this with your link.
StaticLoadClass still finds the class, so I instantiated the object with it.

FName Name{ "TesteBP" };
const FString PackageName{ "/Game/" + Name.ToString() + "." + Name.ToString() + "_C" };

if (const TObjectPtr<UClass> Class{ StaticLoadClass(UObject::StaticClass(), nullptr, *PackageName) })
{
	if (const TObjectPtr<UBlueprintGeneratedClass> Blueprint{ Cast<UBlueprintGeneratedClass>(Class) })
	{
		if (const TObjectPtr<UMyBlueprintParentClass> MyObj{ Blueprint->GetDefaultObject<UMyBlueprintParentClass>() })
		{
			return MyObj;
		}
	}
}
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.