Unreal Engine 4 —— Asset Manager介绍

unreal PrimaryAssetType

Unreal Engine 4 —— Asset Manager介绍

https://blog.csdn.net/noahzuo/article/details/78815596

背景(题外话)

如果不出意外的话,未来的一段时间将要回归UE4的全职开发了。用了将近9个月的unity,或多或少能感受到这两款商业引擎的设计理念的差异,也开阔了不少思路。在使用Unity 5的过程中发现它的Asset Management做的很不错,回想起来当初用UE4做Console的时候也没有遇到过这种需求 —— 不过这个功能在移动端应该是很常用的需求,因此也做个记录吧……
涉及到的类

    Assest
    Asset指的是在Content Browser中看到的那些物件。贴图,BP,音频和地图等都属于Asset.
    Asset Registry
    Asset Registry是资源注册表,其中存储了每个特定的asset的有用的信息。这些信息会在asset被储存的时候进行更新。
    Streamable Managers
    Streamable Managers负责进行读取物件并将其放在内存中。
    Primary Assets
    Primary Assets指的是在游戏中可以进行手动载入/释放的东西。包括地图文件以及一些游戏相关的物件,例如character classs或者inventory items.
    Secondary Assets
    Secondary Assets指的是其他的那些Assets了,例如贴图和声音等。这一类型的assets是根据Primary Assets来自动进行载入的。
    Asset Bundle
    Asset Bundle是一个Asset的列表,用于将一堆Asset在runtime的时候载入。
    Asset Manager
    Asset Manager是一个可选的全局单例类,用于管理primary assets和asset bundles,这些东西在runtime的时候很有用。

Primary Assets

Primary Asset指的是可以针对于UObject::GetPrimaryAssetId()返回一个有效的值的UObject。

对于默认的工程,所有在/Game/Maps路径下的Maps会被设为Primary Assets,而所有其他的assets如果需要设定为Primary Assets,都需要手动指定。

所有的Primary Assets是通过FPrimaryAssetId来进行引用的,FPrimaryAssetId拥有如下的属性:

    PrimaryAssetType:这指的是一个用于描述物件的逻辑类型的名字,通常是基类的名字。例如,我们有两个继承自同一个本地类AWeapon的BPAWeaponRangedGrenade_C和AWeaponMeleeHammer_C,那么它们会有同样的PrimaryAssetType——"Weapon"
    PrimaryAssetName:这指的是用于描述这个asset的名字。通常来说,这就是这个object的名字(short name),但是对于例如说maps来说,这个值就是对应的asset path。
    PrimaryAssetType:PrimaryAssetName可以组成整个游戏实例中的asset的唯一的描述。当客户端在和服务端通信的时候,就可以通过这个字符串来确认某个物件。例如,"Weapon:BattleAxe_Tier2"本质上和"/Game/Items/Weapons/Axes/BattleAxe_Tier2.BattleAxe_Tier2_C"是一样的。
    在FPrimaryAssetId中分别有两个FName的Tag,分别是PrimaryAssetTypeTag和PrimaryAssetNameTag。因此,当一个Primary Asset被保存了之后,就可以直接在Asset Registry中通过这两个Tag来找到这个Asset。

Streamable Manager

FStreamableManager可以用来处理assets的读取,并且将其在被需要的时候保存在内存中。针对不同的操作,可以有不同的Streamable Manager。FStreamableManager可以与FStreamableHandle一起工作,来更好的处理物件在内存中的生命周期。

    FStreamableHandle是一个用于处理assets读取的结构体。通常来讲,在streaming operation会返回一个shared pointer,这个shared pointer就是用于追踪这个结构体的。当一个handle是active的时候,它就可以确保它引用的那些assets是在内存中的了。
    FStreamableHandle从Loading开始就被激活了,当这个handle被显式cancel或者release的时候,将被disactive。
    FStreamableHandle::ReleaseHandle()可以用来被显示调用。但是当所有的指向这个handle的只能指针被销毁的时候被隐式调用。
    FStreamableHandle::CancelHandle()是用来中断Loading过程的接口。这个函数被调用后,Loading将会被中断,并且将取消Loading完成过后的所有回调函数。
    FStreamableHandle::WaitUntilComplete()将阻断线程,知道所需的asset被成功载入为止。这个函数被调用时,所需的asset的载入优先级将被设为最高(通过将其移到优先级队列的top来实现),并且不会影响其他的异步载入操作,因此通常比LoadObject函数更快。
    RequestAsyncLoad是基本的stream操作。可以传入一个FStringAssetReference或者一个FStringAssetReference的列表。调用了这个操作之后,引擎会试图去Load这些Assets,并且在Loading完毕之后调用回调函数。同时,这个函数会返回一个Streamable Handle的shared pointer来供后期调用。
    RequestSyncLoad是RequestAsyncLoad的同步版本。这个函数要么会进行异步载入并且调用WaitUntilComplete函数,要么直接调用LoadObject函数 —— 哪个更快就调哪个。
    LoadSynchronous是另一种Loading的方式,这个函数会返回一个asset,并且这个函数可以有模版安全的版本。
    这些函数都有bManageActiveHandle的参数,默认为false —— 如果设定为true的话,会导致streamable manager本身就带有一个这个handle的reference。这样一来的话就需要手动管理以及release这个handle了。

Asset Manager

AssetManager是一个单例的UObject,它提供了在runtime的时候进行查询以及读取Primary Assets的操作。这个东西是原本用于取代ObjectLibraries当前提供的操作的,并且可以对FStreamableManager进行一层封装来处理Async Loading的操作。引擎内置的asset manager只能提供基本的管理操作,但是一些更加复杂的东西,例如caching需要自己实现。Asset Manager的基本操作如下:

    Get():单例的Get操作。
    ScanPathsForPrimaryAssets(Type, Paths, BaseClass):这个函数可以查询特定目录下的某类特定的primary asset,如果在Editor下则直接读取磁盘上的信息,如果在cooked工程中会从asset registry cache中读取asset信息。
    GetPrimaryAssetPath(PrimaryAssetId) : 获得PrimaryAssetId对应的asset的object path。
    GetPrimaryAssetIdForPath(StringReference): 获得object path对应的asset的primary asset id信息,以Type:Name的形式。
    GetPrimaryAssetIdFromData(FAssetData):通过FAssetData来获得对应的Type:Name形式的Primary Asset Id。
    GetPrimaryAssetData(PrimaryAssetId):同理
    GetPrimaryAssetDataList(Type):返回一个所有对应类型的asset列表。
    GetPrimaryAssetObject(PrimaryAssetId):查询这个对应的UObject是否在内存中。如果这个UObject不再内存中,则返回nullptr。
    LoadPrimaryAssets(AssetList, BundleState, Callback, Priority):异步载入这些primary assets和BundleState所引用的所有其他assets。返回一个FStreamableHandle的shared_pointer用于追踪,并且在Loading完成后调用回调函数。
    UnloadPrimaryAssets(AssetList):这个函数会调用这些primary assets的GC。
    ChangeBundleStateForPrimaryAssets(AssetList, Add, Remove):这个函数可以用一种更复杂的方式去处理bundle state。

Asset Bundles

Asset Bundle在Unity中很常见了——总体来说就是显式的primary assets相关的assets列表。

    从底层来看,一个Bundle本质上其实就是一个FName到TArray<FStringAssetReferences>的map。每一个bundle都与一个Primary Asset Id相关。但是……这个东西也可以是一个动态的asset。
    如果需要对普通的Primary Asset生成对应的Asset Bundle,我们需要在自己的Object中加入一个FAssetBundleData的UStruct,并且在进行save操作的时候将这个UStruct进行填充。然后,这些数据就会被写在asset registry tag中,并且在这些asset数据被读取的时候,这个UStruct会被识别并处理。
    AssetBundle meta tag可以被设定为确定的AssetPtr或者StringAssetReference。
    可以通过调用AddDynamicAsset函数来在runtime的时候处理一些特定的asest bundle.
    在Asset Bundle中的任何东西,都会被认为是该primary asset的一部分。这在进行Chunking的时候会非常有用。

其他

整个的AssetManager是一个很大的系统,如果有个例子就更好了。

如果有时间就把Fortnite的例子翻译过来吧……

<全文完>
————————————————
版权声明:本文为CSDN博主「谁允许你直视本大叔的」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/noahzuo/article/details/78815596

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值