What is the goal
I am working on a demo of replacing textures by loading pak at runtime as a phased verification of a larger part of my work
The assets in the game are divided into two packages. The texture assets in the main pak package A.uasset are called the old version. The texture assets in the pack pak package A.uasset are called the new version. They are in the same path under the mount point and have the same name. I hope that the game does not need the pack pak file when it starts, but downloads the pack pak file later to replace the texture. So, I need to load the pak file manually and implement something to update the texture.
What is the problem
After loading the backup pak during game runtime, the mount method returns true, indicating that the mount is successful. The priority is also set to 1000, and AssetRegistry.ScanPathsSynchronous is also called, but the texture is still not refreshed to the content in the backup pak
However, if the backup pak is renamed to _P.pak before loading the game for the first time and placed in the directory where the main pak is located, that is, the two are at the same level, then according to the mechanism already written by UE, the backup pak can be loaded first. At this time, the image asset of the game when it is started is the content in the backup pak.
This also shows that there is no problem with my backup pak. It is simply a problem of loading method.
There are two possibilities
-
After the texture asset has been loaded, no matter how high the priority of the new pak file is when mounting, as long as the texture asset path is the same, the loaded asset will no longer be replaced.
-
Because the image resources have been loaded into memory, although the assets of the new pak have been loaded, this loading only updates the index structure and does not update the memory. Therefore, scanning the AssetRegistry is useless.
What I have try
I have read UE docs about loading pak file:
Primer: Loading Content and Pak Files at Runtime | Epic Developer Community
The docs lets me know about AsssetRegistry, but that is not enough.
I have read others’ question:
The question is about loading a new object that haved be instanced or loaded. But my question is how to load newer version asset from new pak, to replace older version of asset. The two version of asset have same path and same name.
How do I debugging
Package the game as I say, call UnrealPAK to gain my desired main.pak and pack.pak
Replace original pak file by my main.pak, then start packaged game.
When game is running, I call my custom pak loading function. Parameters are: PakFilename
is the absolute path of pack.pak, PakOrder
is 1000, MountPoint
is \Game\
. My desired asset to replace is definitely in /Game/
, because I have checked in editor.
Edit:
\Game\
is error
Now I wish the texture I loaded is overrided and refreshed, but it didn’t.
My coding
#include "PakBlueprintLibrary.h"
#include "IPlatformFilePak.h"
#include "AssetRegistry/AssetRegistryModule.h"
bool UPakBlueprintLibrary::LoadPakFile(const FString& PakFilename, int PakOrder, const FString& MountPoint)
{
IPlatformFile& InnerPlatform = FPlatformFileManager::Get().GetPlatformFile();
FPakPlatformFile* PakPlatformFile = new FPakPlatformFile();
PakPlatformFile->Initialize(&InnerPlatform, TEXT(""));
FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile);
FPakFile* Pak = new FPakFile(&InnerPlatform, *PakFilename, false);
if (!Pak->IsValid())
{
return false;
}
if(!PakPlatformFile->Mount(*PakFilename, PakOrder, *MountPoint))
{
return false;
}
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
AssetRegistry.ScanPathsSynchronous({MountPoint}, true);
return true;
}
Platform
OS: Windows11
UE: 4.27.2
Anyone knows some information? Or some guidance about which part of UE source code should I investiagte? Thanks!