Unreal 资源管理&加载
Unreal 资源管理&加载
什么是Cook?
- 资源的序列化
- 将资源转换为引擎定义的组织形式
- 在Unity中这环节是不可见的
- 在编辑器模式下,Editor借助 Library来完成这个环节;
- Resource、AssetBundle模式下都经过了序列化(源码中称为Transfer)
参与Cook的资源分类
>> \Engine\Source\Runtime\Engine\Public\Engine\ICookInfo.h
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
28
29
30
31
32
33
34
enum class EInstigator : uint8
{
InvalidCategory,
NotYetRequested,
Unspecified,
StartupPackage,
AlwaysCookMap,
IniMapSection,
IniAllMaps,
CommandLinePackage,
CommandLineDirectory,
DirectoryToAlwaysCook,
FullDepotSearch,
GameDefaultObject,
InputSettingsIni,
StartupSoftObjectPath,
PackagingSettingsMapToCook,
CookModificationDelegate,
ModifyCookDelegate,
AssetManagerModifyCook,
AssetManagerModifyDLCCook,
TargetPlatformExtraPackagesToCook,
ConsoleCommand,
CookOnTheFly,
IterativeCook,
PreviousAssetRegistry,
RequestPackageFunction,
Dependency,
HardDependency,
SoftDependency,
Unsolicited,
GeneratedPackage,
Count,
};
那么UE中这些资源的 cook 的大致流程是怎样的?
- 在代码中形如
Uxxx::Serialize(FArchive& Ar)
类比 Unity 中的Transfer
函数 - UE中这个是 UObject 的虚函数
不同资源的Cook流程是怎么样的?有什么需要注意和优化方向?
如何 Cook指定的资源?
UE里的依赖是怎么处理的?
资源的一些概念
去查阅一下文档里这些相关的信息
- Blueprint
- Primary Asset == 有点像打AssetBundle标签
- Secondary Asset == 纹理或网格之类的
IO Store??
资源命名规范
- 文件名 & 路径中不允许包含
.
:
以及其他不可显字符
加载细节
- 加载参数里有 SandBox 是否可以作为加速搜索的入参?
- A list of packages to restrict the search for the object
加载设计
这篇写的不错 资源加载相关 对几个核心API进行了分析
不同的加载API有什么区别
https://github.com/Rootjhon/LoadTester
查找资源
- FindObject
- FindObjectFast
- FindObjectChecked
- FindObjectSafe
- FSoftObjectPath::ResolveObject
同步
- LoadObject
- LoadClass
- LoadPackage
- FSoftObjectPath::TryLoad
- FStreamableManager::RequestSyncLoad
- FStreamableManager::LoadSynchronous
- FlushAsyncLoading(异步转同步)
异步
- LoadPackageAsync
- FStreamableManager::RequestAsyncLoad
加载状态
- GIsSavingPackage
- IsGarbageCollectingOnGameThread
- IsLoading
- GetNumAsyncPackages
- GetAsyncLoadPercentage
- FStreamableManager::IsAsyncLoadComplete
非引擎反序列化资源的线程化
优先队列
lazy同步
- 这个概念由 LoadObject,LoadClass,LoadPackage 这几个同步加载的底层实现改造
- 最终调用的是LoadPackageAsync函数,这就是异步加载的入口,并且最后FlushAsyncLoading,内部阻塞等待,将异步加载转为同步
- 因此,可以将返回 资源加载请求的对象 时,再进行 FlushAsyncLoading 的同步锁定;
当前加载的任务数
- GGameThreadLoadCounter 引擎层面在加载的任务数
- 自己维护一个任务数,可以监控 是否存在不规范调用
资源加载的进度
- GetAsyncLoadPercentage
UObject上的PostLoad 函数似乎可以用来做热重载?
资源卸载
- 常规方式:默认情况下,加载中的资源由引擎持有引用,不会被卸载,加载完成后的资源会依赖引擎的gc卸载。如果没有被使用到,会在下次gc的时候释放掉。如果需要立即释放可以手动强制引擎gc。
- UEngine::ConditionalCollectionGrbage()
- UEngine::ForceGarbageCollection()
- 分类别释放
- UObject : ConditionalBeginDestory => 调用后需保证对象不再被使用(内部逻辑等价于 BeginDestroy )
- Texture\Mesh\Material : ReleaseResource => 会影响渲染队列,可以push到渲染队列里(实际需要去测试一下)
- RenderTarget : FPooledRenderTarget::Release => 回收再利用
- DynamicMaterial : 专用函数?
- Actor\ActorComponent : DestroyActor \ DestroyComponent
- SceneComponent : DestroyPhysicsState \ DestroyRenderState
加载框架设计
主要涉及的几个关键字:
- FLinkerLoad
- CreateLinker
- ImportMap
- ExportMap
- DependsMap
- Object->Serialize [同步加载,反序列化]
- operator«( UObject*& Object )
Ar « Index [UObject 类型属性反序列化]
- FAsyncPackage
- EventDrivenSerializeExport
- StaticAllocateObject
- Object->Serialize
UClass
- SerializeTaggedProperties
- Ar « Tag [读取属性Tag,反序列化]
类:
- UPackage
- UObject
SerializeScriptProperties
- FDuplicateDataWriter
- FObjectInstancingGraph
具体修改内容:
- UObject (Parent)
- 【内存数据刷新】
- RefreshResourceObject
- Serialize
- 记录当前反序列化Object
- ThreadContext.SerializedObject = this
- 【内存数据刷新】
SerializeScriptProperties
- FLinkerLoad
- operator«( UObject*& Object )
- Ar « Index [UObject 类型属性反序列化]
- 抽取Object到Asset映射
- 记录反序列化属性Value
- KnownMissingPackageRefObjectMap
- KnownMissingPackageRefObjectQuick
UClass
- SerializeTaggedProperties
- Ar « Tag [读取属性Tag,反序列化 记录反序列化属性Tag信息]
FDuplicateDataWriter
- GetDuplicatedObject
- 抽取Object到Asset映射
FObjectInstancingGraph
- InstancePropertyValue
- GetInstancedSubobject
- 抽取Object到Asset映射
主要流程就是:
- 创建Package
- Object 反序列化,过程中遇到本地不存在资源,进行记录
- 下载所需资源
- 更新记录的Object对象数据,刷新显示
本文由作者按照 CC BY 4.0 进行授权