UE热更新:资产管理与审计工具

在前面的文章中,介绍了基础包的拆分规则和实现,在基础的打包规则稳定之后,日常开发中的关注重点就转向侧重于项目的资产管理和包体资源审计、分析项目中的资产大小和冗余情况等。

本篇文章介绍UE中的资源打包配置、常用的资产管理方式以及资产审计工具等工程实践,热更新系列文章的资源管理篇,也是对上一篇文章UE4热更新:拆分基础包的内容补充。

打包配置

UE中的资源打包选项可以在Project Settings-Packaging中进行设置,可以在这里设置是否生成Pak以及资源进包的规则。

关于UE4基础包中包含的具体内容,我在Unreal Open Day的热更新方案中有介绍,有兴趣的可以去看这个视频:Unreal Open Day 2020 虚幻引擎4全平台热更新方案 | 查利鹏

  • UsePakFile:是否使用Pak文件,如果启用,会把游戏用到的资源都打包到pak文件中,如果不启用,则会把cook之后的uasset/config/shaderbytecode/assetregistry/uplugin/uproject等文件按照项目内的路径规则每个文件单独存放。

  • Generate Chunks:是否打包时生成Chunk,如果项目内具有划分Chunk的规则,勾选此选项会生成多个pak文件。
  • Generate No Chunks:不生成Chunk
  • Chunk Hard Reference Only:只把Hard引用的资源打包到Chunk中,Soft的引用不会进包。
  • PakFile Compression Formats:指定Pak的压缩算法,该参数会传递给UnrealPak,详见:ModularFeature:为 UE4 集成 ZSTD 压缩算法
  • ShareMaterialShaderCode:是否共享ShaderCode,会生成ushaderbytecode到包内,可以减小包体的大小。

下面这些参数就是具体的控制把资源打到包内的规则:

Directories to never cook的目录不会被打到包内。

Additional Non-Asset Directories to Package用来把一些non-uasset文件打到包内,比如Lua或者其他的一些表格文件等。

Chunk划分

UE具有划分Chunk的功能,每个Chunk在打包时会生成一个单独的pak文件,可以通过创建一个PrimaryAssetLable来进行设置。

UE关于划分Chunk的文档:

创建PrimaryAssetLable资源:

注意,在默认情况下,引擎中的资源和在项目设置中配置的Non-Asset的资源是强制打包到Chunk0中的,如果包含了引擎的资源也不会把它们打包到当前Chunk中(设置Priority也无用),用PrimaryAssetLable只能控制uasset的划分。

这部分代码在:

Runtime/Engine/Private/AssetManager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
bool UAssetManager::GetPackageChunkIds(FName PackageName, const ITargetPlatform* TargetPlatform, const TArray<int32>& ExistingChunkList, TArray<int32>& OutChunkList, TArray<int32>* OutOverrideChunkList) const
{
// Include preset chunks
OutChunkList.Append(ExistingChunkList);
if (OutOverrideChunkList)
{
OutOverrideChunkList->Append(ExistingChunkList);
}

if (PackageName.ToString().StartsWith(TEXT("/Engine/"), ESearchCase::CaseSensitive))
{
// Some engine content is only referenced by string, make sure it's all in chunk 0 to avoid issues
OutChunkList.AddUnique(0);

if (OutOverrideChunkList)
{
OutOverrideChunkList->AddUnique(0);
}
}

// Add all chunk ids from the asset rules of managers. By default priority will not override other chunks
TSet<FPrimaryAssetId> Managers;
Managers.Reserve(128);

GetPackageManagers(PackageName, true, Managers);
return GetPrimaryAssetSetChunkIds(Managers, TargetPlatform, ExistingChunkList, OutChunkList);
}

通过编辑创建的PrimaryAssetLable资源的参数来控制它所管理的Chunk的资源:

  • Priority:指定当前Chunk的优先级,因为可能有几个Chunk中都会包含同一个资源,如何决定这个资源打包到哪个chunk中去?通过指定优先级可以控制资产的冗余,如果优先级相同则每个Chunk中都会包含一份。

  • ChunkID:指定生成Chunk的ID值,生成的pak文件命名规则为:pakchunk0-WindowsNoEditor.pak,pakchunk后的数字就是ChunkID值。

  • ApplyRecursively:对所管理的资源进行递归依赖分析,但不包含优先级更高的Chunk管理的资产。

  • CookRule:当前Chunk的Cook规则,可以实现控制该PrimaryAssetLable管理的资源都不打包(NeverCook)

    • UnKnown:如果有引用则进行Cook
    • NeverCook:从不进行Cook,该部分资源不会被打包
    • DevelopmentCook:如果有引用则在Development模式中Cook,Production时不Cook
    • DevelopmentAlwaysCook:在Development模式中均进行Cook,Production不Cook
    • AlwayCook:在任何情况下都执行Cook
  • Lable Assets in My Directory:当前PrimaryAssetLable所在目录(以及子目录)下的资源都归它管理。

  • IsRuntimeLabel:设置PrimaryAssetLable资源本身在运行时可用,并且会打到包内,该选项不会对它标记的资产有影响。

  • Explicit Assets:指定所管理的资源文件,与HotPatcher中的IncludeSpecifyAsset类似。

  • ExplicitBlueprints:指定管理某种类型的蓝图资产。

  • AssetCollection:指定Collection名字。

可以看到通过上述的参数能够实现以下的资产管理功能:

  1. 指定目录
  2. 指定资源和其依赖
  3. 反向控制上述参数不打到包内(Never Cook)
  4. chunk优先级控制资产冗余

在工程的资产管理中可以组合这几种模式来实现项目的需求:

如果地图副本较多,可以把副本及其资源作为一个Chunk管理,如果有一些资源被其他chunk中重复引用,可以把这部分资源单独作为chunk管理并设置成较高优先级。

可以在资源预览(Reference Viewer)中看到Chunk直接引用的资源,需要勾选Show Management References,被Chunk引用的类型是EAssetRegistryDependencyType::Manage,并不是普通的Hard/Soft资源引用关系。

但是PrimaryAssetLable也有个缺点,不能指定non-uasset文件,如果我们有更新lua或者db、表格之类的需求,无法通过PrimaryAssetLable机制来进行打包和划分,这个需求可以通过HotPatcher实现,HotPatcher也实现了类似PrimaryAssetLable的Chunk的功能用于拆分Patch,详情见之前的文章:UE4 资源热更打包工具 HotPatcher

当我们使用了PrimaryAssetLable并且在Project Settings-Packaging中开启了Generate Chunks,在打包时就会按照配置的规则生成多个pak文件了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
D:\PCVersion\WindowsNoEditor>tree /a /f
| ClientGame.exe
| Manifest_DebugFiles_Win64.txt
| Manifest_NonUFSFiles_Win64.txt
|
+---Engine
\---ClientGame
+---Binaries
| \---Win64
| ClientGame.exe
| ClientGame.pdb
|
+---Content
| \---Paks
| pakchunk0-WindowsNoEditor.pak
| pakchunk1-WindowsNoEditor.pak
| pakchunk2-WindowsNoEditor.pak
|
\---Plugins

这里生成的多个chunks的pak文件可以设置在上一篇拆分基础包的规则文件中,实现基础包拆分的功能。

资产审计

Asset Audit

在上面的两节中分别介绍了UE中打包的项目配置和为资产划分Chunk的方式,本节会介绍在日常开发中进行资产审计的方式和工具。

通过Chunk划分,这一节的介绍,我们可以标记一些资源打包到pak中去,但是我们无法很直观地知道被这个chunk所管理的资源有多少,在每个平台的大小,因为UE打包时需要执行cook,每个资源的最终大小都是平台相关的,所以需要一种方法能够直观地看到基础包内Chunk的资源划分。

UE提供了资产审计工具:Asset Audit,可以在Editor中通过Windows-Developer Tools-Asset Audit打开。

可以看到资源路径、大小、位于哪些Chunk中等一系列的信息,便于排查资源大小和Chunk中的资源冗余。

前面已经提到了Editor里的看到的资源大小和最终打到包内的大小是不一样的,在Asset Audit窗口的右上角会列出已经打包的平台(Saved/Cooked)下的平台。

Asset Audit是需要读取DevelopmentAssetRegistry.bin文件来得到某个平台的资源信息的,当打包某个平台之后,存储在以下路径中:

1
Client\Saved\Cooked\WindowsNoEditor\Client\Metadata\DevelopmentAssetRegistry.bin

这个文件记录着某个平台执行完Cook之后资源的大小以及引用关系等信息,注意Cook之后的资源如Texture2D等设置的压缩均以执行,但是打包成pak时也会执行压缩,这里列出来的大小是没有经过打包pak压缩的Cook资源之后的原始大小。

可以在打包时自动提取Cooked目录下的Metadata目录,在AssetAudit窗口的右上角选择Custom,选择DevelopmentAssetRegistry.bin文件即可。

UnrealPakViewer

UnrealPakViewer是一个可以查看Pak文件的工具,可以方便地查看Pak中的文件信息以及从Pak中解压文件。

作者还支持了指定加载AssetRegistry文件,因为默认情况下AssetRistry.bin只在Chunk0中包含,打开不包含AssetRegistry.bin的pak是无法预览出资源类型的,可以通过指定外部文件的AssetRegistry.bin来使用,UnrealPakViewer可以与AssetAudit结合起来用作为日常工程的资产审计工具。

全文完,若有不足之处请评论指正。

微信扫描二维码,关注我的公众号。

本文标题:UE热更新:资产管理与审计工具
文章作者:查利鹏
发布时间:2021年03月09日 18时16分
本文字数:本文一共有3.7k字
原始链接:https://imzlp.com/posts/3675/
许可协议: CC BY-NC-SA 4.0
文章禁止全文转载,摘要转发请保留原文链接及作者信息,谢谢!
您的捐赠将鼓励我继续创作!