写的有点乱。。。。。
这里有一些可供参考的文档:
UE4 Pak 相关知识总结 https://arcecho.github.io/2017/07/02/UE4-Pak-%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86%E6%80%BB%E7%BB%93/
UnrealPak的使用笔记 https://blog.ch-wind.com/unrealpak-note/
UE4补丁与DLC https://blog.ch-wind.com/ue4-patch-release-dlc/
pak文件是游戏中的资源打包后生成的文件。
对游戏的更新,如果只是资源更新,而没有c++的更新,可通过只更新pak文件进行。
生成更新用的pak,通常我们是通过基础release版本,来生成patch(补丁),可通过项目启动程序的配置启动描述文件来生成。生成更新pak的方法如下:
http://api.unrealengine.com/CHN/Engine/Deployment/Patching/index.html
在打包时,如果指定生成release版本2.0。在没有指定生成补丁时,会在release 2.0目录中的对应版本目录2.0下生成一个包含所有资源文件pak文件。
如果生成release版本2.0指定了基于1.0生产补丁。则会在指定的基础版本1.0的目录中,生成一个_p.pak结尾的补丁包,而对应的版本2.0目录下没有任何pak文件。
如果接下来生成release版本3.0时仍然指定了基于2.0生产补丁。则会在2.0 生成一个包含全部资源的_p.pak结尾的补丁包。3.0目录下没有pak。
如果接下来生成release版本4.0时仍然指定了基于3.0生产补丁。则会在3.0 生成一个包含全部资源的_p.pak结尾的补丁包。4.0目录下没有pak。
如果按上面生成release版本的同时生成补丁的方法进行补丁更新。补丁包会越来越大。且相当于全部替换。
所以一般在生成release版本时,不应该同时指定生成补丁包。
生成补丁包应该单独生成。
通常我们在生成下一个版本时。我们设置两个启动描述文件。
一个用于生成版本。
一个用于生成基于上一个版本的补丁。
|
在生成版本的描述文件中。我们这样设置: |
在生成补丁的描述文件中。我们这样设置 |
|
|
|
我们在F:\package\2.0 depend 1.0\WindowsNoEditor\PakAndDLC\Content\Paks 文件夹中,可以找到 补丁文件: 【项目名称】-【目标平台】_0_P.pak
这就是我们需要的。我们可以将它改成 [项目名称]_1.0_2.0_P.pak
对pak文件的挂载的优先级决定了,搜索资源的顺序。
当我们更新了资源后,需要让我们搜索资源时优先搜索新的pak文件。
挂载pak是在FPakPlatformFile::Mount 函数中, 当挂载时,我们同时指定了pak的优先级。
然后我们就可以把我们这个1.0版本的Saved/Paks/ 目录下, 然后就可以使用了
之后我们还可以生成[项目名称]_2.0_3.0_P.pak. 同样放在Saved/Paks/ 目录下。
因为FPakPlatformFile::Mount 函数中 对 以_数字_p.pak结尾的 pak文件挂载优先级的特殊处理关系。
[项目名称]_2.0_3.0_P.pak 优先级最高, 之后是[项目名称]_1.0_2.0_P.pak, 再之后才是【项目名称】-【目标平台】.pak
在实际适用中,我们可以根据版本顺序。从http服务器上依次下载从当前客户端版本到最新版本的pak补丁。
然后根据版本顺序,设置FPakPlatformFile::Mount中的挂载优先级。为了使用方便。如果我们的版本补丁是链式的(也就是1.0-2.0 2.0-3.0, 而不是 1.0-3.0 中间跨越了几个版本)。我们可以用【项目名称】_整数版本号_P.pak为版本名称。
如果我们需要使用蓝图的移动补丁工具节点来安装我们的补丁的话。我们可以使用UE4中的BuildPatchTool.exe 来生成需要的manifest文件和 CloudDir。移动补丁工具节点
该工具是在Engine\Binaries\Win64 文件夹中。
BuildPatchTool.exe -mode=PatchGeneration -BuildRoot=F:\test -CloudDir=F:\CloudDir -AppName="appName" -AppLaunch="" -AppArgs="" -BuildVersion="1.0"
通常我们只需要指定-BuildRoot和-CloudDir。BuildRoot 代表了存放pak的文件夹。CloudDir代表了生成的文件存放的位置。
其他参数不能省略。 APPName和BuildVersion 将生成manifest文件的名称。这里就是appName1.0.manifest。
将补丁复制到Saved/Paks/文件夹中可以在c++中导出下面两个函数
#include "GenericPlatform/GenericPlatformFile.h"
bool UMyBlueprintFunctionLibrary::copyfile(const FString To, const FString From)
{
return IPlatformFile::GetPlatformPhysical().CopyFile(*To, *From);
}
bool UMyBlueprintFunctionLibrary::CreateDirectoryTree(const FString directory)
{
return IPlatformFile::GetPlatformPhysical().CreateDirectoryTree(*directory);
}
将补丁 pak 文件放入设备上 FPakPlatformFile::GetPakFolders 所设置的任何 pak 搜索目录后,它将自动装载
pak 搜索目录:
OutPakFolders.Add(FString::Printf(TEXT("%sPaks/"), *FPaths::ProjectContentDir()));
OutPakFolders.Add(FString::Printf(TEXT("%sPaks/"), *FPaths::ProjectSavedDir()));
OutPakFolders.Add(FString::Printf(TEXT("%sPaks/"), *FPaths::EngineContentDir()));
也就是 工程的 工程名/Content/Paks/ 目录, 工程名/Saved/Paks/ 目录,和 Engine/Content/Paks/ 目录
这三个目录中的pak文件将在游戏启动时自动加载!! 我们可以把下载过来的需要自动加载的pak放在工程名/Saved/Paks/ 中。
为了确定各补丁的优先顺序,装载系统使用文件名末尾的 _p 来确定其优先于其他 pak 文件。您可将补丁 pak 文件重命名,但必须 在文件名末尾包括 _p.pak。
FPakPlatformFile::Mount 函数的参数:
bool FPakPlatformFile::Mount(const TCHAR* InPakFilename, uint32 PakOrder, const TCHAR* InPath /*= NULL*/)
inPakFileName:是加载的pak的文件路径。
PakOrder:是加载的优先级, 数值越大优先级越高。
对于以_P.pak为结尾的文件:
如果是以_[数字]_P.pak为结尾(比如_1_P.pak),PakOrder=PakOrder +100*(数字取整+1),
如果不是以_[数字]_P.pak为结尾则PakOrder=PakOrder+100
inPath 是挂载的路径。通常设为NULL。代表/Game
FPakPlatformFile::Initialize 会加载FPakPlatformFile::GetPakFolders返回的文件夹中的所有的还未加载过的PAK文件。
这时候PAK挂载的路径inPath 都是NULL
PakOrder 通过 FPakPlatformFile::GetPakOrderFromPakFilePath 获得
int32 FPakPlatformFile::GetPakOrderFromPakFilePath(const FString& PakFilePath)
{
if (PakFilePath.StartsWith(FString::Printf(TEXT("%sPaks/%s-"), *FPaths::ProjectContentDir(), FApp::GetProjectName())))
{
return 4;
}
else if (PakFilePath.StartsWith(FPaths::ProjectContentDir()))
{
return 3;
}
else if (PakFilePath.StartsWith(FPaths::EngineContentDir()))
{
return 2;
}
else if (PakFilePath.StartsWith(FPaths::ProjectSavedDir()))
{
return 1;
}
return 0;
}
首先存在于工程名/Content/Paks/ 中的以工程名加-开头的pak文件的pakOrder 返回4
其他存在于工程名/Content/Paks/ 中的pak文件的pakOrder 返回3
存在于Engine/Content/Paks/ 中的pak文件的pakOrder 返回2
存在于工程名/Saved/Paks/ 中的pak文件的pakOrder 返回1
其他返回0