AssetBundle加载API

在Unity 5当中,可以通过4个不同的API来加载AssetBundle,4个API可以用两个条件来区分:

  1. AssetBundle是 LZMA压缩、 LZ4压缩还是不压缩的
  2. 加载AssetBundle的平台

这4个API分别是:

1 AssetBundle.LoadFromMemoryAsync

Unity不推荐使用这个API

Unity 5.3.3更新: 这个API在Unity 5.3.3被重命名,之前版本叫 AssetBundle.CreateFromMemory,功能是一样的。

AssetBundle.LoadFromMemoryAsync 从托管代码的字节数组(C#的byte[])中加载AssetBundle。它总是会从本地内存中开辟一段连续内存,然后从托管代码的字节数组中拷贝源数据到这段新分配的内存中。如果 AssetBundle 是 LZMA 压缩格式的,拷贝过程中 AssetBundle 会被解压。而 LZ4 压缩格式或者不压缩的 AssetBundle 会原封不动地拷贝过去。

这个 API 内存消耗的峰值最少是 AssetBundle 大小的两倍:一个是 API 创建的本地内存,一个是传递给 API 的托管代码数组。利用这个 API 加载资源之后,这个加载资源将会在内存中出现 3 份拷贝:一个是托管代码字节数组,一个是 AssetBundle 的本地内存,第三个是在 GPU 或者系统内存中的资源本身。

2 AssetBundle.LoadFromFile

Unity 5.3更新: 这个 API 在 Unity 5.3.3 被重命名。在之前的版本中叫做 AssetBundle.CreateFromFile,功能是一样的。

AssetBundle.LoadFromFile 是一个被设计用来从本地存储中(如硬盘和 SD 卡)加载未压缩的 AssetBundle、高效的API。如果 AssetBundle 未压缩或者使用 LZ4 压缩,这个 API 表现如下:

移动设备: API 只会加载 AssetBundle 的 头部数据, 其他的数据保留在磁盘中。当调用加载的方法(也就是 AssetBundle.Load)或者他们的实例 Id 被解引用时才会被按需加载,在这种情况下没有额外的内存开销的。

Unity 编辑器: 这个 API 会将整个 AssetBundle 加载进内存,就像使用 AssetBundle.LoadFromMemoryAsync那样,而不是按需从磁盘上读取资源。当 AssetBundle 加载时,在Unity编辑的Profiler面板会出现一个峰值,但是在实际设备上面并不会出现,所以如果你要优化这个峰值,需要在实际设备上面重新测试。

注意: 在 Unity 5.3 之前版本的安卓设备上,从 StreamingAssets 目录下加载 AssetBundle 会失败。这是因为 StreamingAssets 下的内容会被打包到一个压缩的 .jar 文件中。更详细的内容,请参照 AssetBundle 使用模式 的 “4.2.1项目部署” 小节。这个问题在 Unity 5.4 中已经修复。Unity 5.4 或者以后版本编译的游戏可以使用这个 API 来从 StreamingAssets 里面加载 AssetBundle。

注意: 对于LZMA压缩的AssetBundle来说,AssetBundle.LoadFromFile API在有的Unity版本上会出现总是加载不成功的问题,这个问题在 Unity 5.3.7f1、 Unity 5.4.3f1和之后的版本修复了。(译注:这里是说在 Unity 5.3.7f1之前、 5.4.0f1到Unity 5.4.3f1(不包括)的版本这个API都是有Bug的,之后的版本修复了这个API加载不了LZMA压缩AssetBundle的问题。)

3 WWW.LoadFromCacheOrDownload

WWW.LoadFromCacheOrDownload 对于从远端服务器和本地存储中加载对象来说很有用,可以使用 file:// 链接地址从本地加载文件。如果 AssetBundle 已经在 Unity 的缓存中存在,则它会表现的跟 AssetBundle.LoadFromFile 一样。

如果 AssetBundle 没有被缓存,WWW.LoadFromCacheOrDownload 会从 AssetBundle 的源地址读取它。如果 AssetBundle 是压缩格式,它会使用一个 worker 线程来解压 AssetBundle 并且写入到缓存当中。如果AssetBundle没有压缩,worker 线程会直接将它写入缓存中。

一旦 AssetBundle 被缓存了,WWW.LoadFromCacheOrDownload 会从缓存中加载 Header 信息和未压缩的 AssetBundle。之后这个 API 表现就跟 AssetBundle.LoadFromFile 一样了。

注意: 当数据被解压并写到缓存的同时,WWW 对象会在本地内存中保留一份 AssetBundle 字节的完整拷贝。这个 AssetBundle 的额外的拷贝是用来支持 WWW.bytes 属性的。

由于 WWW 对象缓存 AssetBundle 的字节数组的开销,这里推荐开发者使用 WWW.LoadFromCacheOrDownload API的 AssetBundle 保持尽可能小(最多几 M )。也推荐开发者在内存有限平台上,如移动设备,确保他们的代码在同时只有一个 AssetBundle 在下载来避免内存峰值。关于 AssetBundle 的大小,请参照 AssetBundle 使用模式 章节中的 “4.3资源分配策略” 小结。

注意: 每调用一次这个 API 都会生成一个新的 worker 线程,要当心多次调用这个 API 的时候多产生多个线程的问题。如果有 5 到 10 个 AssetBundle 需要下载,建议代码只让少数几个 AssetBundle 同时下载。

4 AssetBundleDownloadHandler

在 Unity 5.3 的移动平台上,Unity 引入了 UnityWebRequest API,它比 Unity 的 WWW API 更灵活。UnityWebRequest 可以让开发者指定 Unity 怎么样处理数据和避免不必要的内存开销。使用 UnityWebRequest 去下载一个 AssetBundle 的最简单的方式就是调用 UnityWebRequest.GetAssetBundle API。

在这篇文章中,我们感兴趣的类是 DownloadHandlerAssetBundle。使用时,它的行为跟 WWW.LoadFromCacheOrDownload 类似。它使用 worker 线程去下载数据到固定大小 Buffer 中,然后根据Doanload Hanlder 的设置,把 Buffer 中的数据写到临时存储或者 AssetBundle 缓存中。LZMA 格式压缩的 AssetBudnle 会在下载和缓存过程中被解压。

所有的这些操作都是发生在 Unity底层代码(native code)里,就避免了撑大C#托管堆(managed heap),另外, Download Handler在Unity底层代码也 不 保留所有下载字节数组的拷贝,更加减少了下载AssetBundle的内存开销。

当下载完成之后,Doanload Handler 的 assetBundle 属性用来访问已下载的 AssetBundle,就像对下载后的 AssetBundle 执行了 AssetBundle.LoadFromFile 一样。

UnityWebRequeset 也支持像 WWW.LoadFromCacheOrDownload 一样缓存机制。如果给 UnityWebRequest 对象提供给了缓存信息,并且请求的 AssetBundle 已经在 Unity 的缓存中,AssetBundle 会马上生效并且这个 API 就像 AssetBundle.LoadFromFile 一样操作它。

注意: Unity AssetBundle 缓存机制在 WWW.LoadFromCacheOrDownload 和 UnityWebReuqest 之间是共享的,一个API下载过AssetBundle就其它的API来说缓存也生效。

注意: 不像 WWW, UnityWebRequest 系统拥有一个内部的 worker 线程池,和内部的任务系统去确保开发者不会同时开启大量线程去下载,目前这个线程池的大小是不能配置的。

5 建议

一般的,应该尽可能的使用 AssetBundle.LoadFromFile,这个 API 在速度,磁盘使用率和运行时内存方面都是最高效的。

对于需要下载 AssetBundle 或者给 AssetBundle 打补丁的项目,强烈推荐在 Unity 5.3 或更新版本中使用 UnityWebRequest ,在 Unity 5.2 或者更老版本中使用 WWW.LoadFromCacheOrDownload。就像在下一章的 “4.2 部署” 章节中提到,可以在项目安装的时候(下载器)将 AssetBundle包 解压从而事先准备好 AssetBundle缓存。

当使用 WWW.LoadFromCacheOrDownload 时,为了避免内存峰值引起的程序闪退,强烈推荐确保 AssetBundle 保持在项目最大内存预算的 2-3%。对于大多数项目而言,AssetBundle 的文件大小最好不要大于 5M ,并且不要超过 2 个 AssetBundle 在同时下载。

当使用 WWW.LoadFromCacheOrDownload 或者 UnityWebRequest 是,确保下载的代码在加载完 AssetBundle 后正确的调用 Dispose。C# 的 using 是确保 WWW 或者 UnityWebRequest 的 Dispose 方法会被调用 的最简便的做法。

对于一个有着大型开发团队的项目来说,自定义下载器对于缓存和下载新内容是很有必要的。写一个自定义的下载器是一个艰巨的工程,特别是下载器要和AssetBundle.LoadFromFile兼容的话。更多详情,查看下章节中的 “4.2部署” 章节。

AssetBundle加载API的更多相关文章

  1. Unity5.x版本AssetBundle加载研究

    之前说了 “Unity5.x版本AssetBundle打包研究”,没看过的请先看一下:http://www.shihuanjue.com/?p=57 再来看本文,有一定的连接性. 先梳理一下思路: 要 ...

  2. U3D assetbundle加载与卸载的深入理解

    using UnityEngine; using System.Collections; using System; public class testLoadFromAB : MonoBehavio ...

  3. U3D assetbundle加载

    using UnityEngine; using System.Collections; public class testLoadFromAB : MonoBehaviour { IEnumerat ...

  4. Unity5系列资源管理AssetBundle——加载

    上次我们进行了AssetBundle打包,现在我们还把打包的资源加载到我们的游戏中.在加载之前,我们需要把打包好的Bundle包裹放到服务器上,如果没有,也可以使用XAMPP搭建本地服务器. 加载的A ...

  5. Unity5-ABSystem(三):AssetBundle加载

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/lodypig/article/detai ...

  6. [原]unity5 AssetBundle 加载

    本文unity版本5.1.3 一.现有的打包教程: 1.http://liweizhaolili.blog.163.com/blog/static/16230744201541410275298/ 阿 ...

  7. Android开发中如何加载API源码帮助开发

    在eclipse中添加android源码既可以帮助我们的开发,又能使我们边开发边学习. android环境的搭建:http://blog.csdn.net/dawanganban/article/de ...

  8. 详谈 Unity3D AssetBundle 资源加载,结合实际项目开发实例

    第一次搞资源更新方面,这里只说更新,加载,AssetBundle资源加载,谈谈自己的理解,以及自己在项目中遇到的那些神坑,现在回想一下,真的是自己跪着过来的,说多了,都是泪. 我这边是安卓AssetB ...

  9. AssetBundle异步加载被中断的问题

    刘 刘泰言创建于 1 年前 在使用异步接口 yield return AssetBundle.ASyncLoad的时候,难免会想到:这个异步处理完之前如何Cancel掉这个任务?也就是一个AssetB ...

随机推荐

  1. Alpha 冲刺报告(8/10)

    Alpha 冲刺报告(8/10) 队名:洛基小队 峻雄(组长) 已完成:关于角色属性的脚本编码 明日计划:提升脚本的完成度 剩余任务:角色的属性脚本 困难:缺乏编程经验,很难自己独立完成编写,只能根据 ...

  2. 什么是SEO服务,企业为什么要做SEO?

    SEO服务: 1. 网站提交服务 网站提交是非常重要的,尤其是英文网站(英文网站可以提交到世界各国比较出色的搜索引擎).网站的提交,增加了潜在客户找到网站的机会.网站的提交是一个不断更新的过程,因为搜 ...

  3. 【原创】uWSGI http和http-socket说明

    http 和 http-socket的使用上有一些区别: http: 自己会产生一个http进程(可以认为与nginx同一层)负责路由http请求给worker, http进程和worker之间使用的 ...

  4. Odoo中的甘特图

    转载请注明原文地址:https://www.cnblogs.com/cnodoo/p/9296922.html  甘特图 用图表来衡量实际与预期生产记录之间关系的方法中所使用的图表,亦称甘特进度表或条 ...

  5. logstash 匹配日志格式

    2017-05-15 12:06:17 INFO  me.cinyi.imapp.push.commons.iospush  - 用户ID[1000]-标识[11500], admin推送通知成功, ...

  6. 谷歌浏览器安装POSTMAN

    1.下载postman插件,可以自己到网上下载,也可以点击http://download.csdn.net/detail/u010246789/9528471 2.解压文件,在解压后的文件夹中找到.c ...

  7. http 的request和response 在servlet的应用文件下载

    一)response 我们通过浏览器访问网站的时候,处理响应的是response. 它由三部门组成:响应行.响应头.响应体 作用:往浏览器写东西. 1)响应行 格式:协议/版本  状态码 状态码说明. ...

  8. PAT乙级1001

    https://pintia.cn/problem-sets/994805260223102976/problems/994805325918486528 #include<bits/stdc+ ...

  9. DQL-联合查询

    一.含义union:合并.联合,将多次查询结果合并成一个结果二.语法查询语句1union [all]查询语句2union [all]... 三.意义1.将一条比较复杂的查询语句拆分成多条语句2.适用于 ...

  10. localStorage 和 sessionStorage

    1.概述 以前本地存储使用 cookie.但是 Web 存储需要更加安全和快速.所以就出现了localStorage 和 sessionStorage. 2.sessionStorage,localS ...