Engine content does not load for mounted pak in IOS

Hi guys,
I have been having a problem with DLC mounting for few days, and I’m not able to solve the issue. The thing is I am trying to load custom levels from pak files using the Pak Loader plugin present in the marketplace. As the plugin is just a blueprint wrapper of the c++ classes present in unreal, everything should work fine in IOS as it is working in windows. But that’s not the case. The level mounts with the contents present in the Content folder or /Game/ folder of the plugin content. But it does not load engine content like BP_SkySphere.
Somehow, the mount point to /Engine/ which is the Engine content folder is lost the minute I load the level present in the plugin or DLC or pak file. Has anyone faced this issue before?

The errors are like this [and many more for other engine content]: Couldn’t find file for package /Engine/EngineSky/BP_Sky_Sphere requested by async loading code. NameToLoad: /Engine/EngineSky/BP_Sky_Sphere

Contents of the Pak File

The methodology I’m following is pretty much here [Pak Loader plugin documentation]: PakLoaderPlugin.pdf - Google Drive

I want to do this: Create and package original game. Then I want to create additional PAK files with new meshes/sounds/animations and blueprints based on blueprint in the original game. Original game should not know anything about additional meshes/animations/etc. So I need to create a smart system with AssetRegistry in the original game that scans all PAK files, load/mount them and with AssetRegistry scan those PAK files for all assets.

What I did to achieve my goal: I create and package successfully original game for the target platform (windows standalone). Then in the project, I create additional content and cook them for the target platform. I use UnrealPak.exe to create PAK files for additional content. I am able to load/mount PAK file in the original game by placing PAK file in Paks folder and they load/mount at startup of the game (this sentence is based on the LOG file from the original game, I don’t know how to check if it is true or not). I am able to load/mount PAK file even with code by using FCoreDelegates::OnMountPak.Execute (this sentence is also based on the LOG file from the original game). So loading/mounting PAK files should work well. But now where is the biggest issue. I want to use AssetRegistry to scan for all assets in all PAK files. I tried everything I came up with. I tried ScanPathsSynchronous method, GetAllAssets method. Only what happens is it loads assets from ORIGINAL GAME PAK FILE. It seems that AssetRegistry doesn’t know anything about other PAK files. I tried to tell AssetRegistry where are those files with AddPath method and still doesn’t work.

So my example code what I tried is here:

         FString path1 = FPaths::ConvertRelativePathToFull(FString("../../../TestPaks/Content/Paks/test.pak"));
     FString path2 = FPaths::ConvertRelativePathToFull(FString("../../../TestPaks/Content/Paks/testmaterial.pak"));        

     bool check1 = false;
     bool check2 = false;
     if (FCoreDelegates::OnMountPak.IsBound())
     {
         check1 = FCoreDelegates::OnMountPak.Execute(path1, 0, nullptr); //Number should be 0-4; specifies search order
         check2 = FCoreDelegates::OnMountPak.Execute(path2, 0, nullptr); //Number should be 0-4; specifies search order
     }

     UE_LOG(LogTemp, Warning, TEXT("%s"), *path1);
     UE_LOG(LogTemp, Warning, TEXT("%s"), *path2);

     FString NewString1 = check1 ? "true" : "false";
     FString NewString2 = check2 ? "true" : "false";
     UE_LOG(LogTemp, Warning, TEXT("check 1 = %s"), *NewString1);
     UE_LOG(LogTemp, Warning, TEXT("check 2 = %s"), *NewString2);

     FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
     IAssetRegistry& assetRegistry = AssetRegistryModule.Get();

     TArray<FString> ContentPaths;
     TArray<FAssetData> data;
     //assetRegistry.AddPath(path1);
     FString contentRelativeDir = TEXT("/Game/Paks");
     assetRegistry.AddPath(contentRelativeDir);
     assetRegistry.ScanPathsSynchronous({ contentRelativeDir });
     //assetRegistry.SearchAllAssets(true);
     assetRegistry.GetAllAssets(data, false);

     assetRegistry.GetAllCachedPaths(ContentPaths);
     for (FString& data : ContentPaths)
     {
         UE_LOG(LogTemp, Warning, TEXT("GetAllCachedPaths: %s"), *data);
     }

     FString NewString = FString::FromInt(data.Num());
     UE_LOG(LogTemp, Warning, TEXT("%s"), *NewString);

     for (int32 i = 0; i < data.Num(); i++)
     {
         FString s = data[i].AssetName.ToString();
         FString ss = data[i].AssetClass.ToString();
         UE_LOG(LogTemp, Warning, TEXT("%s | %s"), *s, *ss);
     }

I tried a lot of versions of paths and nothing is working. I am in this mess around 2 weeks and I don’t have any much more tips on what to do and what will work. So how should this work properly??? I looked in forums here and StackOverflow and there are some solutions, but they don’t work anymore.

1 Like