What is correct way to PAK files, load/mount them and load assets with AssetRegistry?

Hi guys,
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 original game. Original game should not know anything about additional meshes/animations/etc. So I need to create smart system with AssetRegistry in original game that scans all PAK files, load/mount them and with AssetRegistry scan those PAK files for all assets.

What I did to achive my goal:
I create and package successfully original game for target platform (windows standalone). Then in project I create additional content and cook them for target platform. I use UnrealPak.exe to create PAK files for additional content. I am able to load/mount PAK file in 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 original game, I dont 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 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 doesnt know anything about other PAK files. I tried to tell AssetRegistry where are those files with AddPath method and still doesnt 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 dont have any much more tips 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 dont work anymore.

1 Like

Hi Keri,

I have loaded asset from .pak file on UE4.21, you can read this

Hi, GiapTT, thanks for sharing!

why did you use same iterator on the second loop (Filelist)?
and I have a bunch of errors if I change NewAssetName for directory for my additional packages,
how can I paste relative directory to NewAssetName, or better exclude main pak from this iteration?

update: better way using instead FPackageName::GetShortName this FPackageName::TryConvertFilenameToLongPackageName

my little mod

hello 6r0m,
to load assset from pak, u need path to it.
assumed that your asset store at: Content/Pak1/AssetName. uasset
→ path to asset: Game/Pak1/NewAssetName
where new-name-asset may be difference in some types.

  • for Material, StaticMesh: AssetName.uasset → AssetName.AssetName
  • for Blueprint actor: BP_Actor.uasset - > BP_Actor.BP_Actor_C
  • skeleton: I have not yet test :frowning:

hope that will help you.
cheer!

This might be something for you: Pak Loader Plugin in Code Plugins - UE Marketplace