• 【Unity优化】资源管理系列03:AssetBundle 基本原理


    定义:将一个或多个文件,按照一种归档格式,存在一个文件中,Unity可以索引并序列化其中的文件

    操作:加载/卸载AB自身、加载卸载AB中某个资源

    作用:在游戏安装后,继续分发和更新非代码资源

    1)减小游戏包体

    2)减小运行时内存压力

    3)针对不同设备/平台,加载不同资源

    AB结构

    1)数据头:identifier、压缩类型、manifest

    manifest:查找表,key是对象名,value中包含一个字节索引,定位数据段中对象位置

    2)数据段:资源系列化后的原始数据

    三种压缩类型

    1)LZMA:所有资源的序列化数据,被压缩进同一个字节数组

    2)LZ4:每个资源的序列化数据,单独被压缩为字节数据

    3)不压缩:原始字节数据

    压缩类型对比

    1)LZMA:

    优点:原始AB小

    缺点:想要加载其中一个资源,需要解压整个AB;运行时占用内存大

    2)LZ4(推荐):

    优点:想要加载其中一个资源,只需要解压相关数据块;运行时占用内存小

    缺点:原始AB大

    加载AB

    1)AssetBundle.LoadFromMemory

    说明:不推荐,两倍AB内存占用,三倍资源内存占用

    2)AssetBundle.LoadFromFile

    说明:推荐,只加载数据头,之后按需加载资源

    补充:在Editor模式下,异步方法会加载整个AB,会出现内存峰值;真机中没有

    3)UnityWebRequest 的 DownloadHandlerAssetBundle

    ① 可以使用 UnityWebRequest.GetAssetBundle,也可使用 DownloadHandler

    ② DownloadHandler 使用工作线程,流式下载,存入固定大小buffer,然后传给临时存储或 AB cache。这些操作都有原生代码实现,不会产生堆分配。且不会额外保存下载字节数据的拷贝,减少内存占用。

    ③ 如果AB是LZMA压缩格式,在下载的时候会被解压缩,并以LZ4格式缓存。

    ④ AB下载完成后,通过 DownloadHandler 的 assetBundle 获取AB。

    ⑤ 如果AB之前已被加载,且在缓存中,则会立即返回,此时和 LoadFromFile 功能类似

    4)WWW.LoadFromCacheOrDownload

    说明:Unity5.6之前使用,已废弃

    5)建议

    ① LoadFromFile,建议在任何可用的场景使用,无论是加载速度、硬盘占用、运行时内存占用,该API都是最高效的。

    ② UnityWebRequest,需要下载AB时使用;记得调用 Dispose 或 Using。

    ③ 如果自研下载器,需要适配 LoadFromFile 方法。

    加载AB中资源

    1)三种API

    ① LoadAsset(Async)

    ② LoadAllAssets(Async)

    ③ LoadAssetWithSubAssets(Async)

    2)同步与异步对比

    ① 同步方法:至少比异步快一帧;缺点是在资源加载完毕前,会阻塞主线程

    ② 异步方法:可以在一帧内加载多个资源,不阻塞主线程

    3)LoadAllAssets(Async)

    适用场景:从一个AB中加载大部分资源,且这些资源相互独立。

    优点:比多次调用 LoadAsset 快

    AB策略:如果一个AB中,超过66%的资源需要同时加载,则建议将这部分分离出来单独打包

    4)LoadAssetWithSubAssets(Async)

    适用场景:当需要加载一个由多个小资源组合而成的大资源时

    举例:FBX模型及其动画、精灵图集及其精灵

    5)资源加载的一些细节

    ① 从存储中加载对象数据,发生在工作线程上。

    ② 多个工作线程,使得多个对象可以同时被反序列化、处理、整合。

    ③ 当一个对象被加载完毕,Awake方法被调用,从下一帧开始,该对象可被引擎使用。

    ④ 对象加载在一帧中的时间不超过 time-slice,该值由 ThreadPriority 决定。

    ⑤ 发起异步调用,和对象被引擎可用,这两步间至少需要一帧,因此相同条件下,同步方法要比异步方法快一帧。

    6)AB依赖

    ① AB间的相互依赖可以通过 AssetDatabase 和 AssetBundleManifest 获取

    ② 在加载一个对象前,要先加载它依赖的所有AB。Unity不会帮忙自动加载,要自己实现

    7)AssetBundle manifests

    ① 被包含在一个以父文件夹命名的AB中

    ② 包含了AB中对象之间的引用信息

    ③ manifest AB 和其他 AB 一样,可以被加载、缓存、卸载

    ④ 使用 GetAllAssetBundles 方法获取所有包含 AB 列表

    ⑤ 使用 GetAllDependencies 方法返回该AB的所有依赖

    ⑥ 使用 GetDirectDependencies 方法返回该AB的直接依赖

    ⑦ 上面两个方法都会分配 string 数组,不要在性能敏感处使用

    8)建议

    ① 在性能敏感的代码之前,尽可能预加载需要的资源

  • 相关阅读:
    使用Chrome开发者工具研究JavaScript的垃圾回收机制
    Java JDK目录下的jmap和jhat工具的使用方式
    Java注解@Cacheable的工作原理
    使用Java JUnit框架里的@Rule注解的用法举例
    使用Java JUnit框架里的@SuiteClasses注解管理测试用例
    Java JUnit框架里@Category注解的工作原理
    使用SAP CRM mock框架进行单元测试的设计
    将ABAP透明表的定义(元数据)解析出来导入到剪切板(clipboard)里
    SAP ABAP Netweaver里的胖接口(fat interface)
    关于STM32的FLASH操作【转载】
  • 原文地址:https://www.cnblogs.com/hearthstone/p/13357862.html
Copyright © 2020-2023  润新知