x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Failed to find asset in mounted pak

Hello everyone. I've been strugling with loading an asset from a mounted pak file and I don't seem to find the correct way to do this. I've created the function down below that mounts the desired pak (and succeeds) but when loading the assets it always fails. Funny enough when loading the assets synchronously it finds and load them but for some reason async load always fails to find them (on debug, developement and shipping builds). I will really apreciate if someone could give me some guidance.

To make it clearer here is the testing im doing: - Looking for pak in the PersistentDownloadDir - Mount the pak to /Game/TestingContent/ - Reading all the files inside the pak with a visitor (which always work). - Using the listed files to generate unreal like soft paths (for instance: "/Game/TestingContent/TestingTexture.TestingTexture"). - lod sync succeeds (in editor) but async load fails in both developement and shipping builds.

Heres the code:

 void UNigisUtils::MountPakAndStartAssetLoading(const FString & PakFolder, const FString& PakName, const FString& MountPoint, TArray<FString>& AssetStrings, bool bSyncPreloadAssets)
 {
     UE_LOG(LogTemp, Log, TEXT("============= START LOADING PAK ============="));
     if (!PakFolder.IsEmpty() && !PakName.IsEmpty() && PakName.Right(3).Equals(TEXT("pak"), ESearchCase::IgnoreCase))
     {
         IPlatformFile* PreviousPlatformFile = nullptr;
         FPakPlatformFile *PlatformFile = nullptr;
         if (FString(FPlatformFileManager::Get().GetPlatformFile().GetName()).Equals(FString(TEXT("PakFile"))))
         {
             PlatformFile = static_cast<FPakPlatformFile*>(&FPlatformFileManager::Get().GetPlatformFile());
         }
         else
         {
             PlatformFile = new FPakPlatformFile();
 
             if (!PlatformFile->Initialize(&FPlatformFileManager::Get().GetPlatformFile(), TEXT("")))
             {
                 UE_LOG(LogTemp, Error, TEXT("FPakPlatformFile failed to initialize"));
                 return;
             }
             PreviousPlatformFile = &FPlatformFileManager::Get().GetPlatformFile();
             FPlatformFileManager::Get().SetPlatformFile(*PlatformFile);
         }
 
         FString FullPakFolder(FPaths::ConvertRelativePathToFull(PakFolder));
         if (!PlatformFile->DirectoryExists(*FullPakFolder))
         {
             UE_LOG(LogTemp, Error, TEXT("Directory not found: %s"), *FullPakFolder);
             return;
         }
         else UE_LOG(LogTemp, Warning, TEXT("Pak folder verified: %s"), *FullPakFolder);
 
         if (FCoreDelegates::OnMountPak.IsBound())
         {
             // Print files in pak
             struct FilesDump : public IPlatformFile::FDirectoryVisitor
             {
                 FString mp_PakName;
                 TArray<FString> Files;
 
                 FilesDump(FString &PakfileName)
                     : mp_PakName(PakfileName)
                 {}
 
                 virtual bool Visit(const TCHAR *FilenameOrDirectory, bool bIsDirectory)
                 {
                     if (bIsDirectory)
                     {
                         UE_LOG(LogTemp, Log, TEXT("Found DIR in %s: %s"), *mp_PakName, FilenameOrDirectory);
                     }
                     else
                     {
                         const FString Filename(FilenameOrDirectory);
                         if (Filename.Contains(TEXT(".umap")) || Filename.Contains(TEXT(".uasset")))
                         {
                             Files.Add(FilenameOrDirectory);
                             UE_LOG(LogTemp, Log, TEXT("Found FILE in %s: %s"), *mp_PakName, FilenameOrDirectory);
                         }
                     }
                     return true;
                 }
             };
 
             FString PakfileName = PakName;
             FilesDump Visitor(PakfileName);
             FString FullPath = FPaths::Combine(PakFolder, PakName);
 
             FPakFile PakFile(PlatformFile, *FullPath, false);
             if (PakFile.IsValid())
             {
                 FString InMountPoint = MountPoint;
                 FPaths::MakePathRelativeTo(InMountPoint, *FPaths::ProjectContentDir());
                 InMountPoint = FString("/Game/" + InMountPoint);
 
                 PakFile.SetMountPoint(*InMountPoint);
                 //if (PlatformFile->Mount(*FullPath, 4, *InMountPoint))
                 if(FCoreDelegates::OnMountPak.Execute(FullPath, 4, &Visitor))
                 {
                     UE_LOG(LogTemp, Log, TEXT("Pak Mount success!"));    
                     UE_LOG(LogTemp, Warning, TEXT("Reading Pak Contents..."));
                     LoadedAssets.Empty();
 
                     TArray<FString> Files;
                     PakFile.FindFilesAtPath(Files, *InMountPoint, true, false, true);
 
                     //PlatformFile->IterateDirectoryRecursively(*MountPoint, Visitor);
 
                     UE_LOG(LogTemp, Warning, TEXT("\n Generating Asset References..."));
                     TArray<FSoftObjectPath> ObjectPaths;
                     UE_LOG(LogTemp, Log, TEXT("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"));
                     for (FString File : Files)
                     {
                         FString Filename, FileExtn;
                         int32 LastSlashIndex;
                         File.FindLastChar(*TEXT("/"), LastSlashIndex);
                         FString FileOnly = File.RightChop(LastSlashIndex + 1); //remove the full size since we want the slash gone too.
                         UE_LOG(LogTemp, Log, TEXT("File: %s ============ Full Path: %s"), *FileOnly, *File);
                         FileOnly.Split(TEXT("."), &Filename, &FileExtn);
 
                         if (FileExtn == TEXT("uasset"))
                         {
                             File = File.Replace(TEXT("uasset"), *Filename);
                             /*int32 ContentFolderIndex = File.Find(TEXT("/Content"), ESearchCase::Type::CaseSensitive, ESearchDir::Type::FromEnd);
                             FString RelativePath = File.RightChop(ContentFolderIndex + 8);
                             FString AssetPath("/Game" + RelativePath);*/
 
                             FStringAssetReference AssetRef(*File);
                             Assets.Add(TAssetPtr<UObject>(AssetRef));
                             AssetStrings.Add(File);
 
                             //Add a soft object path to the list
                             FSoftObjectPath SoftObjectPath(File);
                             ObjectPaths.Add(SoftObjectPath);
                             SOPtrs.Add(TSoftObjectPtr<UObject>(SoftObjectPath));
 
                             UE_LOG(LogTemp, Log, TEXT("File: %s, Asset reference: %s"), *FileOnly, *AssetRef.ToString());
                         } else UE_LOG(LogTemp, Log, TEXT("File: %s is not an asset file. No reference generated."), *FileOnly)
                         
                         UE_LOG(LogTemp, Log, TEXT("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"));
                     }
                     UE_LOG(LogTemp, Warning, TEXT("\n %d references Generated."), ObjectPaths.Num());
 
                     //Optionally synchronously loads all the references found in the pak
                     if (bSyncPreloadAssets)
                     {
                         UE_LOG(LogTemp, Warning, TEXT("\n Attempting to syncronous load generated references..."));
                         for (const FSoftObjectPath ObjectPath : ObjectPaths)
                         {
                             UObject* LoadedAsset = ObjectPath.TryLoad();
                             if (LoadedAsset != nullptr)
                             {
                                 UE_LOG(LogTemp, Log, TEXT("Asset Reference: %s, Succesfully loaded!"), *ObjectPath.ToString());
                                 LoadedAssets.Add(LoadedAsset);
                             }
                             else UE_LOG(LogTemp, Error, TEXT("Asset Reference: %s, load failed."), *ObjectPath.ToString());
                         }
                         OnAssetsLoadComplete.Broadcast(LoadedAssets);
                     }
                     else
                     {
                         UE_LOG(LogTemp, Warning, TEXT("\n Starting Async load of assets..."));
                         StreamManager.RequestAsyncLoad(ObjectPaths, FStreamableDelegate::CreateUObject(this, &UNigisUtils::ObjectsLoadingComplete));
                     }
                 }
                 else UE_LOG(LogTemp, Error, TEXT("Pak Mount failed."));
             }
             
         }
         else UE_LOG(LogTemp, Error, TEXT("\"OnMountPak\" Core delegate is not bound."));
 
         // return previous platform file manager to the top of the chain, so Unreal doesn't lose it's references
         if (PreviousPlatformFile != nullptr)
         {
             FPlatformFileManager::Get().SetPlatformFile(*PreviousPlatformFile);
         }
     }
     UE_LOG(LogTemp, Log, TEXT("============= END LOADING PAK ============="));
 }

Product Version: UE 4.20
Tags:
more ▼

asked Dec 03 '18 at 02:28 PM in C++ Programming

avatar image

Bariudol
553 19 12 27

avatar image DarkwindRichard Dec 05 '18 at 05:23 PM

Hi Bariudol,

After doing some Googling, it looks like you're using code from an answer to this post. Is there a reason why you omitted PlatformFile->InitializeNewAsyncIO(); before calling FPlatformFileManager::SetPlatformFile?

avatar image Bariudol Dec 11 '18 at 10:22 AM

Wow, i completly missed that for some reason. Il try it out. Thanks!

avatar image Bariudol Dec 12 '18 at 05:10 PM

Hello there again. I've tried that, and modified the function to use the asset registry to find the assets instead of trying to manually find them myself. In editor the function works great and does find the assets in the pak (obviously they dont load because the content is cooked), but when packaging the game, the asset registry never finds the files in the pak althought the mount is suposedly succesful.

Here is a snipet of the new function that works in editor:

 if (bMountSuccessful)
                  {
                      FString MountVirtualPoint = UsedMountPoint;
                      FPaths::MakePathRelativeTo(MountVirtualPoint, *FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()));
                      MountVirtualPoint = MountVirtualPoint.Replace(TEXT("Content/"), TEXT("/Game/"));
                      const FString PackagePath = MountVirtualPoint;
                      MountVirtualPoint.Append(TEXT("/"));
  
                      TArray<FString> Files;
                      PakFile->FindFilesAtPath(Files, *UsedMountPoint, true, false, true);
                      if (Files.Num() > 0)
                      {    
                          FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
                          IAssetRegistry& assetRegistry = AssetRegistryModule.Get();
  
                          TArray<FString> pathsToScan;
                          pathsToScan.Add(TEXT("/Game"));
                          assetRegistry.ScanPathsSynchronous(pathsToScan, true);
  
                          TArray<FAssetData> AllAssetList;
                          TArray<FAssetData> AssetList;
  
                          assetRegistry.GetAllAssets(AllAssetList);
                          assetRegistry.GetAssetsByPath(TEXT("/Game"), AssetList, true, false);

I can post the whole function if needed. Thank you in advance for any possible help!

avatar image DarkwindRichard Dec 13 '18 at 03:12 PM

Hi Bariudol,

You cannot use the asset registry at runtime because it is essentially an editor-only module. Have you also tried looking at this forum post on loading assets from a pak file? I was also able to find an example of async loading in this plugin mentioned in this post.

(comments are locked)
10|2000 characters needed characters left

1 answer: sort voted first

@DarkwindRichard The plugin you mention does not work since version 4.15, it is what we used before updating.

I've managed, however, to get the function working by using the asset registry, turns out that the paths I was giving to it where simply wrong. I don't know if its a bug or what, but in editor the mounting and asset registry works only if mounting with a full path (e.g. E:/Project/Content/), but in a packaged game it works only when mounting to a path relative to the engine (e.g .../.../.../Project/Content); or maybe its just a problem with my function. In any case, intended or not, it now works haha. Thanks for your attention!

more ▼

answered Dec 17 '18 at 10:45 AM

avatar image

Bariudol
553 19 12 27

avatar image nyudeb Mar 08 '19 at 01:40 PM

Hey ! is it possible to have your code ? I'm stuck on this problem since a long time.... I would like to load .pak made with UnrealPak.exe into a project from local path and actually assets are not found with asyncload..

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question