通过 UnrealPak,可以将资源打包成 Pak 文件
Pak文件是UE4游戏生成的数据包文件。
Pak 之前一般先有 Cooked 步骤,将资源烘焙为对应平台支持的资源
Pak 一般放在游戏路径下的Content\Paks
一个Pak 可以包含多个资源,可以是项目资源,也可以是非项目资源,如文本、视频等
可用于热更新或DLC
引擎自动加载 pak 的目录
[ProjectName]/Content/Paks
[ProjectName]/Saved/Paks
Engine/Content/Paks
命令行为一段,为方便阅读,故分行显示
UnrealPak
测试Pak文件能否打开(是否加密)
UnrealPak
UnrealPak
UnrealPak
查看
UnrealPak
UnrealPak
解包
UnrealPak
打包
UnrealPak
更改MountPoint
UnrealPak
UnrealPak
对比两个 pak
UnrealPak
UnrealPak
UnrealPak
Options:
-blocksize=
块大小
-bitwindow=<BitWindow>
-compress
压缩
-order=<OrderingFile>
Cooker烘焙时的顺序文件
-diff (requires 2 filenames first)
比较 pak
-enginedir (specify engine dir for when using ini encryption configs)
引擎目录
-projectdir (specify project dir for when using ini encryption configs)
项目目录
-encrypt
加密
-encryptindex (encrypt the pak file index, making it unusable in unrealpak without supplying the key)
加密索引,不提供key无法解密。可以在Project Setting -> Packaging - > Encrypt the pak index....配置
-encryptionini (specify ini base name to gather encryption settings from)
单独加密ini文件,可以在Project Setting -> Packaging - > Encrypt ini files inside pak files配置
-encryptionkeyoverrideguid (override the encryption key guid used for encrypting data in this pak file)
-sign (generate a signature (.sig) file alongside the pak)
RSA签名:0x<私钥指数>+0x<私钥系数>+0x<公钥指数> 或者指定<KeyFileName>
-aes
32位密钥
-extracttomountpoint (Extract to mount point path of pak file)
-compressionformat[s]=<Format[,format2,...]> (set the format(s) to compress with, falling back on failures)
-fallbackOrderForNonUassetFiles (if order is not specified for ubulk/uexp files, figure out implicit order based on the uasset order. Generally applies only to the cooker order)
-moveBulkAndUptnlOrderLast (move all ubulk and uptnl files after all other resources in the first Order list. Ubulk and uptnl files will be at the end, and will preserve their order)
补充:
-abslog
指定打包日志文件路径
-UTF8Output
UTF8输出
-tempfiles=
烘焙文件临时存储
-multiprocess
多线程
patchpaddingalign=
数据块对齐
-generatepatch=
打Patch包时会添加的参数,后面指定要比较的Release文件
-cryptokeys=<Crypto.json>
指定 Crypto.json
为方便使用命令行,设置环境变量
UnrealPak.exe 是独立应用,也可以单独拷贝出来使用
也可以使用 bat 文件。
注意 * 表示该文件夹下的所有目录
默认调用方法
UnrealPak "C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\MyPaks\Maps.pak" "C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Content\Maps*" -compress
文本调用方法
设置ResponseFile
第一个路径为 Cook 后的资源路径
第二个路径为 挂载路径
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Content\Maps\NewMap.uexp" "../../../DesignPatterns/Content/Maps/NewMap.uexp" -compress
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Content\Maps\NewMap.umap" "../../../DesignPatterns/Content/Maps/NewMap.umap" -compress
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Content\Maps\NewMap_BuiltData.uasset" "../../../DesignPatterns/Content/Maps/NewMap_BuiltData.uasset" -compress
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Content\Maps\NewMap_BuiltData.ubulk" "../../../DesignPatterns/Content/Maps/NewMap_BuiltData.ubulk" -compress
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Content\Maps\NewMap_BuiltData.uexp" "../../../DesignPatterns/Content/Maps/NewMap_BuiltData.uexp" -compress
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Content\Maps\LightMap\LightMap.uexp" "../../../DesignPatterns/Content/Maps/LightMap/LightMap.uexp" -compress
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Content\Maps\LightMap\LightMap.umap" "../../../DesignPatterns/Content/Maps/LightMap/LightMap.umap" -compress
执行脚本
UnrealPak "C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\MyPaks\Maps.pak" -create="C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\MyPaks\MyPakLisk.txt"
bat 文件
@ECHO OFF
ECHO ------------------------------------------------------------------
ECHO UnrealPak Strart Create Pak
ECHO ------------------------------------------------------------------
set PakFilename="C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\MyPaks\Maps.pak"
set ResponseFile="C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\MyPaks\MyPakLisk.txt"
set UnrealPak="C:\SoftwareInstallation\EpicGames\UE_4.26\Engine\Binaries\Win64\UnrealPak.exe"
CALL %UnrealPak% %PakFilename% -create=%ResponseFile%
ECHO ------------------------------------------------------------------
ECHO Finished
ECHO ------------------------------------------------------------------
PAUSE
加密pak
unrealpak PAK_NAME.pak -create=ResponseFile -compress -encrypt -encryptindex -aes=32bit_AESKey
// 在\Config\DefaultEncryption.ini文件中查找AES的密钥,4.26 提示用 -cryptokeys
-encryptindex -encryptionini -enginedir="<EngineDir>" -projectdir="<GameDir>" -platform=Windows
// 新版使用,可将项目设置中的 Encryption Key 填入到json中
//json 格式为 { "EncryptionKey": {"Key": "tmAjE6/depliVQgG3XgI60bwrQE2iGgg5n8VRPXrGm0="} }
-encrypt -encryptindex -compress -cryptokeys=<Crypto.json>
项目打包截取的部分日志
可以在项目设置中设置签名与加密
Output from:
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\DesignPatterns.uproject"
"C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\StagedBuilds\WindowsNoEditor\DesignPatterns\Content\Paks\DesignPatterns-WindowsNoEditor.pak"
-create="C:\Users\Alice\AppData\Roaming\Unreal Engine\AutomationTool\Logs\C+SoftwareInstallation+EpicGames+UE_4.26\PakList_DesignPatterns-WindowsNoEditor.txt"
-cryptokeys="C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Saved\Cooked\WindowsNoEditor\DesignPatterns\Metadata\Crypto.json"
-order="C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\Build\WindowsNoEditor\FileOpenOrder\CookerOpenOrder.log"
-encryptindex
-patchpaddingalign=2048
-platform=Windows
-multiprocess
-abslog="C:\Users\Alice\AppData\Roaming\Unreal Engine\AutomationTool\Logs\C+SoftwareInstallation+EpicGames+UE_4.26\UnrealPak-DesignPatterns-WindowsNoEditor-2021.05.22-17.58.51.txt"
解普通 pak
UnrealPak "C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\MyPaks\Maps.pak" -Extract "C:\Users\Alice\Documents\Unreal Projects\DesignPatterns\ExtractPak"
解加密 pak
unrealpak <PakFilename> -Extract <ExtractDir> -aes=32bit_AESKey
unrealpak <PakFilename> -Extract <ExtractDir> -cryptokeys="[ProjectName]\Saved\Cooked\WindowsNoEditor\[ProjectName]\Metadata\Crypto.json"
unrealpak <PakFilename> -Extract -encryptindex -encryptionini -enginedir="<EngineDir>" -projectdir="<GameDir>" -platform=Windows
-Test
-Verify
-Info
-List [-ExcludeDeleted]
必要时需要加上密钥签名
挂载(Mount)
加载(Load)
简单实现用UI切换材质的gong
ToPak 为要打包的资源,不建议和挂载点路径 不一致,容易导致依赖丢失
ToPak
├─ BP_PakTest1.uasset
├─ UMG_Test.uasset
├─ Material
│ ├─ M_Pak.uasset
│ ├─ M_Pak_Inst.uasset
│ └─ M_Pak_Inst1.uasset
└─ Texture
├─ BlueHPTex.uasset
├─ GreyHPTex.uasset
└─ RedHPTex.uasset
BP_PakTest1
UMG_Test
UnrealPak打包
.Build.cs 添加 PakFile 模块
主要代码
TSharedPtr<FPakPlatformFile> PakPlatformFile;IPlatformFile* InnerPlatformFile;
UFUNCTION(BlueprintCallable)
bool LoadPak(const FString& PakPath);
void ALoadPakActor::BeginPlay()
{
Super::BeginPlay();//获取当前使用的平台
InnerPlatformFile = &FPlatformFileManager::Get().GetPlatformFile();
UE_LOG(LogTemp, Warning, TEXT("InnerPlatformFile: %s"), InnerPlatformFile->GetName());
//初始化PakPlatformFile
PakPlatformFile = MakeShareable(new FPakPlatformFile());
PakPlatformFile.Get()->Initialize(InnerPlatformFile, TEXT(""));
}
bool ALoadPakActor::LoadPak(const FString& PakPath)
{
bool Result = false;// 切换到 pak平台
FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile.Get());
// 获取pak文件
TSharedPtr<FPakFile> PakFile = MakeShareable(new FPakFile(InnerPlatformFile, *PakPath, false));
FString MountPoint = PakFile->GetMountPoint();
UE_LOG(LogTemp, Warning, TEXT("Default Mount Point: %s"), *MountPoint);
#if WITH_EDITOR
// PIE模式下,MountPoint 使用绝对路径
// 打包模式下,MountPoint 使用相对路径
MountPoint = FPaths::ConvertRelativePathToFull(MountPoint);
UE_LOG(LogTemp, Warning, TEXT("Default Mount Point Full Path: %s"), *MountPoint);// 设置pak文件的Mount点,因为在制作pak的时候已在文本中设定 mount point,故省略此步骤
MountPoint = FPaths::ProjectContentDir() + TEXT("DLC/");
// 可在此处检测 默认MountPoint的绝对路径释放和本条语句执行结果是否一致
MountPoint = FPaths::ConvertRelativePathToFull(MountPoint);
PakFile->SetMountPoint(*MountPoint);
UE_LOG(LogTemp, Warning, TEXT("New Mount Point Full Path: %s"), *MountPoint);
#endif// 对pak文件进行挂载
if (PakPlatformFile->Mount(*PakPath, 1, *MountPoint))
{
// 加载 pak 里的资源
UClass* BP_PakTestClass = LoadClass<AActor>(nullptr, TEXT("Blueprint'/Game/DLC/BP_PakTest1.BP_PakTest1_C'"));
if (BP_PakTestClass)
{
GetWorld()->SpawnActor<AActor>(BP_PakTestClass, FVector::ZeroVector, FRotator::ZeroRotator);
Result = true;
}
else
UE_LOG(LogTemp, Error, TEXT("Load BP_PakTest1 Class Failed"));
// 遍历 pak 里的资源
TArray<FString> AssetList;
PakFile->FindPrunedFilesAtPath(AssetList, *PakFile->GetMountPoint(), true, false, true);
for (FString itemPath : AssetList)
{
UE_LOG(LogTemp, Warning, TEXT("%-30s\t%s"), *FPackageName::GetShortName(itemPath), *itemPath);
// 此处可异步加载资源
}
}
else
UE_LOG(LogTemp, Error, TEXT("Mount Pak Failed"));
// 设置回原来的PlatformFile, UE4.26
// 不加该条语句,本测试崩溃,报错:Pure Virtual function being called while application was running
FPlatformFileManager::Get().SetPlatformFile(*InnerPlatformFile);
return Result;
}
如果可以挂起,但无法加载,可以测试相对路径与绝对路径的问题
pak 文件右键属性赋值的路径,有时会导致挂载失败(无缘无故的bug调了一下午,烦躁)
PakPlatformFile->Unmount()
可卸载
PakPlatformFile->GetMountedPakFilenames()
获取已加载的pak,可用于检测,避免重复加载
默认使用 Pak里的Mount Point
测试时,PIE模式下挂载成功,但是loadClass 失败,应该是路径的问题.打包后没问题
修改 部分代码
bool ALoadPakActor::LoadPak(const FString& PakPath)
{
bool Result = false;
if (FCoreDelegates::OnMountPak.IsBound())
{
if (FCoreDelegates::OnMountPak.Execute(PakPath, 0, nullptr))
{
UClass* BP_PakTestClass = LoadClass<AActor>(nullptr, TEXT("Blueprint'/Game/DLC/BP_PakTest1.BP_PakTest1_C'"));
if (BP_PakTestClass)
{
GetWorld()->SpawnActor<AActor>(BP_PakTestClass, FVector::ZeroVector, FRotator::ZeroRotator);
Result = true;
}
else
UE_LOG(LogTemp, Error, TEXT("Load BP_PakTest1 Class Failed")); }
else
UE_LOG(LogTemp, Error, TEXT("OnMountPak.Execute() Failed"));
}
else
UE_LOG(LogTemp, Error, TEXT("OnMountPak.IsBound() Failed"));
return Result;
}
由于Pak 并没有包含 Shader,从而导致依赖丢失
解决方法1:ProjectSetting → Packaging → Share Material Shader Code 关闭共享,但这样会使 Shader 变多
解决方法2:将母材质至于项目内,使用 Material Instanse 打包进 pak, PIE 下也可以生效
默认 打包 cook 会生成 Crypto.json,路径为 [ProjectName]\Saved\Cooked\WindowsNoEditor\[ProjectName]\Metadata\Crypto.json
自定义最简 Crypto.json
{
"EncryptionKey": {"Key": "tmAjE6/depliVQgG3XgI60bwrQE2iGgg5n8VRPXrGm0="}
}
打包 pak
UnrealPak "C:\Users\Alice\Documents\Unreal Projects\tips\MyPak\PakTest.pak"
-create="C:\Users\Alice\Documents\Unreal Projects\tips\MyPak\PakList.txt"
-encryptindex
-compress
-cryptokeys="C:\Users\Alice\Documents\Unreal Projects\tips\Config\Crypto.json"
修改代码
// 在挂载前使用,本文调用位置为 ALoadPakActor::LoadPak() 首出
// 绑定PAK解密函数
FCoreDelegates::GetPakEncryptionKeyDelegate().BindUObject(this, &ALoadPakActor::InitEncrypt);
//解密函数,Base64转换
void ALoadPakActor::InitEncrypt(uint8* Key) {
FString KeyStr = TEXT("tmAjE6/depliVQgG3XgI60bwrQE2iGgg5n8VRPXrGm0=");
TArray<uint8> KeyBase64Ary;
FBase64::Decode(KeyStr, KeyBase64Ary);
char* KeyU8 = TCHAR_TO_UTF8(*KeyStr);
FMemory::Memcpy(Key, KeyBase64Ary.GetData(), FAES::FAESKey::KeySize);
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章