又坐了一天月子,继续写文章找状态。

本文是关于 卸载AssetBundle 的一些知识点。

下图是一个最简单的从 AssetBundle 加载 Asset 并 实例化 的流程:

RzIVNni.png (40.22 KB, 下载次数: 0)

RzIVNni.png

2020-2-13 22:10 上传

这里的 Bundle 在加载完 资源A 后就没用了,我们可以通过 AssetBundle.Unload(false) 把它卸掉,只保留住 资源A 。

如果 资源A 也没用了,我们可以通过 Destroy 接口或者 Resources.UnloadAsset 接口销毁它。

题外话,我们需要注意一下 Resources.UnloadAsset 的应用场合:

This function can only be called on Assets that are stored on disk.复制代码

The referenced asset (assetToUnload) will be unloaded from memory. The object will become invalid and can't be loaded back from disk. Any subsequently loaded Scenes or assets that reference the asset on disk will cause a new instance of the object to be loaded from disk. This new instance will not be connected to the previously unloaded object.复制代码

UWA也有相关的回答:

Resources.UnloadAsset仅能释放非GameObject和Component的资源,比如Texture、Mesh等真正的资源。对于由Prefab加载出来的Object或Component,则不能通过该函数来进行释放。

好了,回到上图。

上图描述的场景过于简单,实际项目中, 资源A 可能依赖 其他资源 ,并且 其他资源 又被打进 不同的Bundle 中,如下图:

F3QRnuf.png (83.01 KB, 下载次数: 0)

F3QRnuf.png

2020-2-13 22:10 上传

这个时候,卸载 AssetBundle 就需要一定的 策略 了。

在介绍 卸载策略 之前,我们必须先了解清楚 AssetBundle.Unload 这个函数。

关于AssetBundle.Unload

Unity官方文档对于 AssetBundle.Unload 的描述如下:

public void Unload(bool unloadAllLoadedObjects);

复制代码复制代码

Unloads assets in the bundle.复制代码

When unloadAllLoadedObjects is false, compressed file data for assets inside the bundle will be unloaded, but any actual objects already loaded from this bundle will be kept intact. Of course you won't be able to load any more objects from this bundle.复制代码

When unloadAllLoadedObjects is true, all objects that were loaded from this bundle will be destroyed as well. If there are GameObjects in your Scene referencing those assets, the references to them will become missing.复制代码

AssetBundle.Unload(false)会把 Bundle 卸载,但是已经从 Bundle 里加载出来的 资源 是不会被卸载的。

AssetBundle.Unload(true)不但会卸载 Bundle ,也会卸载已经从 Bundle 里加载出来的 所有资源 ,哪怕这些 资源 还被引用着。

对于用户来说,如果选择 AssetBundle.Unload(true) ,用户必须确保 Bundle 中已经加载的 资源 是没有被引用的,否则就会发生 资源丢失 。

如果选择 AssetBundle.Unload(false) ,用户就要承担起卸载 已加载资源 的责任,如果处理不当,就可能造成 资源重复 ,如下图:

aMVbQvF.png (76.4 KB, 下载次数: 0)

aMVbQvF.png

2020-2-13 22:10 上传

最后,Unity提供了一个 Resources.UnloadUnusedAssets 接口帮助我们销毁没有任何引用的 野资源 ,不过这个函数会扫描全部对象,开销较大,一般只在 切场景 时调用。

卸载AssetBundle的策略

了解 AssetBundle.Unload 的行为后,再来看一下我们采用过的策略。

暗黑血统的策略

最早做 暗黑血统 的时候,我们卸载 AssetBundle 的策略如下:

用 AssetBundle.Unload(false) 来卸载 Bundle 。

加载完资源后立即卸载 叶子节点的Bunlde ,这里 叶子节点 表示 没有被其他Bundle所依赖的Bundle 。

对于 非叶子节点的Bundle ,卸载逻辑完全依靠 引用计数 。

以下图为例:

yEjiqeq.png (86.76 KB, 下载次数: 0)

yEjiqeq.png

2020-2-13 22:10 上传

红框标注的 Bundle 可以在加载完 资源 后立刻卸载。

我们看一下包含 资源A和B的Bundle ,如果我们只加载了 A ,然后就把 Bundle 卸载了,然后我们再加载 B ,这个时候 Bundle 又要被重新加载,如果我再从这个 Bundle 加载 A ,这个时候不是就有 2个A 了?

事实上,因为 第一个A 依然还被我们的 AssetManager 管理着,上层逻辑不会直接从 Bundle 中去加载 A ,而是从 AssetManager的缓存 中去拿,所以上述情况并不会出现。

我们再看一下包含 资源C的Bundle ,如果我们加载完 C 后就把 Bundle 卸载了,然后我们再去加载 G ,由于 G依赖C , C所在的Bundle 会再次被加载,同时加载出一个 新的C ,这就是真正的 资源重复 了。

此外,因为我们的 AssetManager 只会管理 直接加载的资源 ,假设我们先加载了 G , C 做为 G 的依赖被 间接加载 ,此时我们再去直接加载 C 就无法命中 AssetManager 的缓存了。对于这种情况, AssetManager 必须做一些额外记录,稍微有点蛋疼。

最后,考虑一下 引用计数 ,假设我们已经销毁了 G ,那么 G 依赖的所有Bundle引用计数会减 1 ,假设 包含D的Bundle 以及 包含H的Bundle 引用计数都为 0 了,选择 AssetBundle.Unload(false) 的结果是被 间接加载 的 D和H 在 Bundle卸载 后依然存活着,我们的 AssetManager 并没有管理到它们,它们变成了 野资源 。

这一类 野资源 最终得依靠 Resources.UnloadUnusedAssets 来卸载,一般我们在 场景切换 时才做这个操作。

当前项目的策略

暗黑血统的策略在线上工作良好,不过因为 AssetManager 只会管理 直接加载 的资源, AssetBundle.Unload(false) 必须配合 Resources.UnloadUnusedAssets 才能完成一次彻底的资源清除。

当前项目, AssetManager 依然只管理 直接加载 的资源,不过我选择了 AssetBundle.Unload(true) 的策略,并且不再区分 Bundle是否是叶子节点 ,一切卸载的依据都是 引用计数 。

正所谓 Bundle在,资源在,Bundle亡,资源亡 ,:)

以下图为例,最左边一列会标记出每个 Bundle 的引用计数:

BFziia2.png (66.39 KB, 下载次数: 0)

BFziia2.png

2020-2-13 22:10 上传

当我们销毁 资源A ,引用计数变化如下:

2u6byir.png (56.36 KB, 下载次数: 0)

2u6byir.png

2020-2-13 22:10 上传

当我们再销毁 资源B ,部分 Bundle 的引用计数变为0,调用 AssetBundle.Unload(true) 就能把资源及时清理干净了,如下图:

vMzAzuQ.png (55.55 KB, 下载次数: 0)

vMzAzuQ.png

2020-2-13 22:10 上传

只要引用计数没问题,理论上 Resources.UnloadUnusedAssets 也就不用了。

总结

当前项目的方案在 资源回收的及时性 上要优于 暗黑血统 的方案,但是 暗黑血统 因为 提前卸载Bundle 的策略, Bundle数量 会更少一点。

其实早期 暗黑血统 在 提前卸载Bundle 的方案上做得更加激进:只有 被共享的Bundle 才不会被提前卸载,而非我上文所说的 叶子节点 ,当然,要堵不少bug。

考虑到目前 LZ4 的压缩策略,以及 AssetBundle.LoadFromFile 的加载方式,多一点 Bundle 的内存占用不会很高,但是多一点 资源 内存占用就比较高了。

题外话,下图是 UWA 关于 LZ4 和 LZMA 的总结,留图备忘:

UjyuumY.png (114.98 KB, 下载次数: 0)

UjyuumY.png

2020-2-13 22:10 上传

本文就到这里,今年有机会也可以试试Unity推荐的 Addressable Assets 。

assetbundle能不能删除_关于AssetBundle的卸载相关推荐

  1. win10今日热点弹窗怎么删除_今日热点怎么卸载-彻底卸载今日热点的方法 - 河东软件园...

    小编最近在使用win10系统的时候发现自己的电脑每次开机的时候都会弹出今日热点的窗口.你知道什么是今日热点么?今日热点就是新闻的小窗口,在这个界面中会给我们介绍最近的比较受大众关注的新闻信息.有的用户 ...

  2. mfsocket怎样彻底删除_告别无法彻底卸载AutoCAD的烦恼

    自从AutoCAD2010发布以来,有一种烦恼就如影随行.就是2010以上版本,一旦卸载,如果想再次安装,就出现已经安装的提示.然后进入:控制面板中卸载-杀毒软件强力卸载的循环模式.这么折腾一轮之后, ...

  3. tomcat9怎样卸载干净_怎样把360卸载干净

    引用9楼kelejuner的回复:tomcat服务没有关掉,肯定是这个--signature------------------------------------计算机仿真 . 删除掉电脑环境变量中 ...

  4. assetbundle能不能删除_Addressable卸载单个资源的疑问

    1)Addressable卸载单个资源的疑问 ​2)如何判断硬件支持GPU Instance 3)StringBuilder反射实现String报错 4)Unity 2018 RequireES3.1 ...

  5. assetbundle能不能删除_AssetBundle 加载、使用以及卸载

    1.本地异步 1 IEnumerator LoadFromMemoryAsync(stringpath)2 3 {4 5 AssetBundleCreateRequest createRequest ...

  6. assetbundle能不能删除_Unity3d爬坑篇(2)之Assetbundle、Shader和Keyword

    本系列基于:BDFramework .Unity3D 2018.4.0 BDFramework:Simple! Easy! Beautiful! This is a powerful Unity3d ...

  7. go get如何删除_在Go使用Sqlite和Accsee

    我在编写iWrite时,设计了一个字典功能,想通过Sqlite提供查字支持.我在GitHub上找到了这个项目,数据是JSON的,有点乱,我又找到一个mdb格式的字典,这些都是Go里处理. pwxcoo ...

  8. indesign选中不了图片删除_图片神器XnView教程、方法和技巧汇总

    编者按 关于XnView的介绍和概况参阅<「神级图片软件 XnView 解析」XnView MP 和 XnView 哪个好>. 在写完上面这篇文章之后,想整理一些方法和技巧给不太熟悉XnV ...

  9. 2007数据透视表如何删除_删除数据透视表标题中的总和

    2007数据透视表如何删除 When you're building a pivot table, if you add fields to the Values area, Excel automa ...

最新文章

  1. day3----编码-集合-深浅copy-文件操作-函数初识
  2. “后浪95后”吴尚哲的 CVPR 最佳论文:无需任何监督,即可重建三维图像
  3. 每日一皮:修Bug的真实情况...
  4. 二,zabbix与php的一些问题
  5. Eclipse+Web3j开发以太坊应用
  6. 界面原型设计工具Balsamiq、墨刀、Axure、Mockplus
  7. 用鸿蒙取名好吗,“鸿蒙”两个字,还是古人写得好看…
  8. Yum 安装 mysql5.7
  9. HALCON 20.11:深度学习笔记(6)---有监督训练
  10. Java静态代理、动态代理以及CGLIB动态代理
  11. html lt;tablegt;,HTML布局lt;divgt;orlt;tablegt;,
  12. CTF-Web SQL注入
  13. 用连接数据库的方式读取excel
  14. ipad一直卡在白苹果_近万字多图带你玩转iPad——iPad指南
  15. Mindspore | lenet 模型代码
  16. python笔记(三):if循环语句
  17. SQL server数据库的操作步骤·Transact-SQL创建
  18. 搜狗搜索立知问答合作说明
  19. Unraid配置阿里云加速镜像安装荒野无灯qBittorrent镜像
  20. 欧洲专线运输方式有哪些?有哪些优势?

热门文章

  1. kali的ifconfig命令不显示eth0(IP)
  2. nginx 根据请求头判断是安卓还是webq
  3. 在iOS中使用钥匙串访问——sskeychain框架
  4. 想使用“本地项目” 的钥匙串
  5. Grab Pass实现玻璃材质
  6. 《爱自己》《痛彻心扉》《礼物》
  7. android遍历的方法,android中遍历arrayList的四种方法
  8. 父母的10种行为会导致孩子不自信
  9. VS2005安装部署桌面快捷方式和程序快捷方式
  10. 十、基础教程-数据提示框(Tooltip)