Loading an asset at runtime

Hi,

i’m trying to load an asset at runtime, from my plugin but i’m getting a nullptr in return.
I suspect this has to do with incorrect path to an asset.

This is my project dir:

+Project
    +Content
        +MyFolder
            +MyAsset.uasset

So after packaging, at game startup I’ve tried:

FStreamableManager AssetLoader;
	FStringAssetReference AssetRef(FPaths::ConvertRelativePathToFull(FPaths::GameContentDir() / "MyFolder/MyAsset.uasset"));
	auto Asset = AssetLoader.SynchronousLoad(AssetRef);

But the Asset is null (when not using .pak file too)

Is that a correct path? If yes, then why do I get null in return? Note i don’t do this from inside the UObject, is that relevant? Also, is it possible to load an asset from the .pak file the same way?

Thanks for any help

1 Like

Loot at my answer StaticLoadObject in packaged game - C++ - Epic Developer Community Forums
Or another solution - How to find blueprints by parent BP? - Blueprint - Epic Developer Community Forums

 #include "debugProj.h"
  #include "ShipFunctionLibrary.h"
  #include "Runtime/AssetRegistry/Public/AssetData.h"
  
  
  UShipFunctionLibrary::UShipFunctionLibrary(const class FPostConstructInitializeProperties& PCIP)
      : Super(PCIP)
  {
  
  }
  
  UObject * MyGetAsset(FAssetData & asset) {
      if (!asset.IsValid())
      {
          return NULL;
      }
  
      UObject * Asset = FindObject<UObject>(NULL, *asset.ObjectPath.ToString());
      if (Asset == NULL)
      {
          FString tmpstring = asset.ObjectPath.ToString();
          UObject * InOuter = NULL;
          ResolveName(InOuter, tmpstring, true, true);
          
          GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Magenta, TEXT("Now string is ") + tmpstring);
          if (InOuter) {
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Magenta, TEXT("InOuter->GetName is ") + InOuter->GetName());
              Asset = StaticFindObjectFast(UObject::StaticClass(), InOuter, *tmpstring);
          }
          if (Asset) {
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Black, TEXT("WOW I Have Load Something with StaticFindObjectFast!") + Asset->GetName());
              return Asset;
          }
          
          Asset = (UObject *)StaticLoadObject(UBlueprint::StaticClass(), NULL, *asset.ObjectPath.ToString());
          if (!Asset)
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Red, TEXT(" FAILED LOAD Object like BLUEPRINT By StaticLoadObject"));
          else {
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Blue, TEXT(" LOADED like BLUEPRINT By StaticLoadObject"));
              return Asset;
          }
  
          Asset = (UObject *)StaticLoadObject(UObject::StaticClass(), NULL, *asset.ObjectPath.ToString());
          if (!Asset)
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Red, TEXT(" FAILED LOAD Object like UOBJECT By StaticLoadObject"));
          else {
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Blue, TEXT(" LOADED like UOBJECT By StaticLoadObject"));
              return Asset;
          }
  
          Asset = (UObject *)LoadObject<UBlueprint>(NULL, *asset.ObjectPath.ToString());
          if (!Asset)
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Red, TEXT(" FAILED LOAD Object like BLUERPRINT "));
          else {
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Blue, TEXT(" LOADED like BLUEPRINT By LoadObject"));
              return Asset;
          }
  
          Asset = LoadObject<UObject>(NULL, *asset.ObjectPath.ToString());
          if (!Asset)
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Red, TEXT(" EVEN FAILED LOAD Object like UOBJECT "));
          else {
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Blue, TEXT(" LOADED like UOBJECT By LoadObject"));
              return Asset;
          }        
      }
  
      return (UObject*)Asset;
  }
  
  TSubclassOf<AShip> UShipFunctionLibrary::GetShip(const FString & name)
  {
      UObjectLibrary * lib = UObjectLibrary::CreateLibrary(AShip::StaticClass(), true, GIsEditor);
      lib->AddToRoot();
      int32 loaded = lib->LoadBlueprintAssetDataFromPath("/Game/Ships");
      GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Cyan, FString::FromInt(loaded) + TEXT(" objects loaded for lib - ") + name);
  
      TArray<FAssetData> Assets;
      lib->GetAssetDataList(Assets);
      for (int32 i = 0; i < Assets.Num(); ++i) {
          FAssetData& assetData = Assets[i];
          GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Get ship: check obj - ") + assetData.AssetName.ToString());
          if (assetData.AssetName.ToString() == name) {
              GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("AssetFound - ") + assetData.AssetName.ToString());
  
              if (!MyGetAsset(assetData))
                  GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Get ship: Failed to load object by GetAsset - ") + assetData.AssetName.ToString());
  
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Green, TEXT("INFO Class Name - ") + assetData.GetClass()->GetName());
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Green, TEXT("INFO FullName - ") + assetData.GetFullName());
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Green, TEXT("INFO AssetClass - ") + assetData.AssetClass.ToString());
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Green, TEXT("INFO ObjectPath - ") + assetData.ObjectPath.ToString());
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Green, TEXT("INFO IsAssetLoaded - ") + (assetData.IsAssetLoaded() ? FString("YES") : FString("NO")));
              GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Green, TEXT("INFO IsValid - ") + (assetData.IsValid() ? FString("YES") : FString("NO")));            
                      //UBlueprint * bp = Cast<UBlueprint>(assetData.GetAsset());
              UBlueprint * bp = Cast<UBlueprint>(MyGetAsset(assetData));
              if (bp) {
                  GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Get ship: bleprint cast done for asset - ") + assetData.AssetName.ToString());
                  if (bp->GeneratedClass->IsChildOf(AShip::StaticClass())) {
                      return *(bp->GeneratedClass);
                  }
                  else {
                      GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Get ship: Class isn`t cild of AShip- ") + assetData.AssetName.ToString());
                  }
              }
              else {
                  GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Get ship: bleprint cast FAILED for asset - ") + assetData.AssetName.ToString());
              }
          }
      }
      return NULL;
  }

That is a lot of code but I would just like to know what I do wrong? What should be the correct path? You’re also loading using UObjectLibrary

Ok, it seems like the path to assets should be

"/Game/PathRelativeToContentFolder"

without the .uasset extension.

Then FStreamableManager works fine, for packaged and compressed content too.

As of 4.16 I now have to use “/Game/Asset.Asset” instead of “/Game/Asset” which worked before. In addition to switching to LoadSynchronous.