综述
1)一个AB通过 LoadFromFile 被加载时,只有头信息被加载到内存,因此只占用几千字节。但是如果需要加载大量AB,则会产生一定影响。
2)管理AB及其资源,最重要的是要理解 AssetBundle.Unload 使用 true 还是 false 参数,以及何时调用。
① Unload(False):只卸载头信息;不卸载从AB中复制实例化的资源对象
② Unload(Ture):头信息、从AB中复制实例化的资源对象全都卸载
Unload(Ture) 细节
1)错误使用:报资源丢失错误
2)两种使用方式:
① 在适当时机,比如 loading 时,卸载所有 AB
② 管理AB中每个资源对象,进行引用计数,当AB中所有资源都不被引用时,卸载该AB
Unload(False)细节
1)错误使用:导致内存中出现重复资源;
2)两种方法卸载已加载进内存的资源:
① 移除对资源的所有引用,然后调用 Resources.UnloadUnusedAssets
② non-additively 地加载场景,Unity自动清除旧场景内所有资源对象,并调用 UnloadUnusedAssets
卸载方案
1)在类似 loading 这样的时机,卸载旧资源,加载新资源
2)最简单的方式,是以场景为单位打包资源,加载新场景时卸载整个旧场景
3)将需要同时加载的资源,打进同一个AB
分发AB
1)随游戏一起安装:一般主机、PC游戏采用
① 不需要更新的AB
② 要更新的AB的初始版本
2)游戏安装后,从网络下载更新:移动游戏采用
① 减小初始包体
下载AB细节
1)如果AB是LZMA压缩,则被解压缓存在内存,或再被压缩为LZ4格式
2)如果AB是LZ4格式,则不做其他处理,直接缓存在内存
3)如果缓存已满,则删除最远未使用的AB
内置AB缓存细节
1)通过 UnityWebRequest 下载的AB,被存在Unity内置AB缓存中
2)UnityWebRequest 的 GetAssetBundle 方法时,可传入 Version 参数。需要说明,该参数不包含在AB中,也不由AB系统生成,而是游戏每次第一次加载AB时开发自行设置,也可使用 manifest 文件中的 CRC 作为 version(但是不要使用AssetBundleManifest.GetAssetBundleHash(),因为不是真的hash算法)。
3)如果 version 参数与缓存中同名AB相同,则加载缓存中AB;如果不同,则下载更新。
4)AB缓存系统仅通过文件名识别是否是同一个AB,而不是通过URI。因此可以先从StreamingAssets加载AB,再通过 UnityWebRequest 下载AB,此时路径可以不同。
5)如果想要更细粒度的控制权,可从 Caching 提供的多个缓存中选择需要的缓存。用于备份或降级备用,比如同时缓存低清和高清资源。
6)Caching.expirationDelay:如果AB在N秒内没有被引用,则自动从缓存删除
7)Caching.maximumAvailableDiskSpace:如果超过空间,则删除最远使用的AB
Streaming Assets 细节
1)任何类型资源都可以放入StreamingAssets
2)编译打包时,StreamingAssets内资源被复制进入最终包
3)在运行时,可通过 Application.streamingAssetsPath 获取 StreamingAssets 路径
4)安卓相关:
① StreamingAssets存储在APK中,压缩算法取决于Unity版本,可通过解压APK查看是否被压缩。如果StreamingAssets被压缩,则 AssetBundle.LoadFromFile() 会比较慢;也可以使用 UnityWebRequest.GetAssetBundle() 将资源解压并缓存,代价是增加内存占用。
② 可将项目导出为 Gradle 项目,在打包时添加AB相关扩展,然后编辑 build.gradle 文件,将AB扩展设置为 noCompress。之后再使用 AssetBundle.LoadFromFile() 加载AB,就不需要解压缩。
5)在有些平台,StreamingAssets不可写,此时可用 WWW.LoadFromCacheOrDownload 或自制下载器。
需要自制下载器的情形
1)对AB缓存需要更细粒度的控制
2)需要实现定制压缩策略
3)需要针对特定平台实现特定需求,比如要使用 iOS 后台下载API
4)AB必须使用SSL协议分发,比如PC平台,Unity没有提供很好的SSL支持