1.pak的MountPoint的计算
UE4在创建pak文件时会对MountPoint进行计算,用一句话来概括计算逻辑就是:UE4会收集所有打包到pak中的文件,然后提取它们目录的公共部分作为MountPoint
下面以一个例子来说明。假设我们有3个文件需要打包到pak中,它们的路径分别为"../../../MyProject/Content/A.uasset"、"../../../MyProject/B.uasset"以及"../../../C.uasset"。
- 计算开始时,首先获取最长的路径,为"../../../MyProject/Content/"
- 接着开始遍历每个文件
- 遍历到"../../../MyProject/B.uasset"时,其路径为"../../../MyProject/“,并不包含"../../../MyProject/Content/",因此公共路径变为"../../../MyProject/“
- 同理,当遍历到"../../../C.uasset"时,公共路径变为"../../../"
- 此时所有文件处理完毕,MountPoint就是"../../../",会被写入pak文件中
2.FPackageName::RegisterMountPoint
根据上面的算法,不同project的pak,uasset的路径都会带上"MyProject/Content/"和"MyProject2/Content/"这样的路径。
加载的时候,需要增加一个全局的MountPoint来替换这个加载路径
3.获取生成pak的Project Name
根据pak的生成规则,需要获取到pak工程对应的Project Name
这里使用"/Mod/"来作为pak的RootPath.
4.加载pak并设置MountPoint
//搜索pak文件
TArray<FString> Result;
IFileManager::Get().FindFiles(Result, *Dir, TEXT("*.pak"));
FPakPlatformFile* PakFileMgr = (FPakPlatformFile*)FPlatformFileManager::Get().GetPlatformFile(FPakPlatformFile::GetTypeName());
for (auto& Pair : Result)
{
auto FilePath = Dir + Pair;
UE_LOG(LogTemp, Warning, TEXT("PreLoadMod %s"), *FilePath);
FPakFile* Pak = new FPakFile(&PlatformFile, *FilePath, false);
if (Pak->IsValid())
{
FString MountPoint(*Pak->GetMountPoint()); //获取Pak上的挂载点
UE_LOG(LogTemp, Warning, TEXT("GetMountPoint %s"), *MountPoint);
//从pak文件名中获取打包的ProjectName
FString Left, Right;
FPaths::GetBaseFilename(FilePath).Split(TEXT("-"), &Left, &Right);
MountPoint.ReplaceInline(TEXT("../../../"), *FPaths::ProjectDir());
Pak->SetMountPoint(*MountPoint);
//设置pak的全局搜索路径
FPackageName::RegisterMountPoint("/Mod/", Pak->GetMountPoint()+ Left + TEXT("/Content/"));
if (PakFileMgr->Mount(*(Dir + Pair), 0, *Pak->GetMountPoint()))
{
//带上/Mod/作为搜索路径,避免默认从/Game/中搜索
UGameplayStatics::OpenLevel(GetWorld(),FName(TEXT("/Mod/Test")));
}
}