当前位置: 首页 > news >正文

Unity 加载AssetBundle

Unity 加载AssetBundle

https://segmentfault.com/a/1190000019656656

随着Unity版本的更新,加载AssetBundle的API也在不断变化,熟悉这些API才获得更好的性能,在这里对加载方式做个整理与总结。

WWW

(官方已淘汰WWW类,如果是5.x之前的老版本工程可以继续使用WWW,如果是5.x之后的工程请使用UnityWebRequest类替代)
Unty4.x - 5.x 用WWW类加载
WWW.LoadFromCacheOrDownload() 通过Url和版本号自动缓存资源包 注意必须是资源包 不能是其他格式 不能加密

www加载样例:

using UnityEngine;
using System.Collections;

public class LoadFromCacheOrDownloadExample : MonoBehaviour
{
    IEnumerator Start()
    {
        while (!Caching.ready)
            yield return null;

        using (var www = WWW.LoadFromCacheOrDownload("http://myserver.com/myassetBundle.unity3d", 5))
        {
            yield return www;
            if (!string.IsNullOrEmpty(www.error))
            {
                Debug.Log(www.error);
                yield return null;
            }
            var myLoadedAssetBundle = www.assetBundle;

            var asset = myLoadedAssetBundle.mainAsset;
        }
    }
}

UnityWebRequest

Unity2018.1以后 官方建议用UnityWebRequest类代替WWW类 据说WWW有性能问题
UnityWebRequest.GetAssetBundle() 兼容WWW.LoadFromCacheOrDownload()的功能 并进行了扩展
UnityWebRequest加载样例:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

/// <summary>
/// 下载测试
/// <para>原文地址:https://segmentfault.com/a/1190000019656656</para>
/// </summary>
public class WebRequestTest : MonoBehaviour {

    private void Start () {
        StartCoroutine(DoLoadFile());
        //StartCoroutine(DoLoadTexture());
        //StartCoroutine(DoLoadAssetBundle());
    }

    // 下载文本或二进制文件
    private IEnumerator DoLoadFile() {
        string url = Application.streamingAssetsPath + "/" + "test.txt";
        using (UnityWebRequest request = UnityWebRequest.Get(url)) {
            yield return request.SendWebRequest();
            if (request.isHttpError || request.isNetworkError) {
                // 下载出错
                print(request.error);
            } else {
                // 下载完成
                string text = request.downloadHandler.text;
                byte[] bytes = request.downloadHandler.data;
                // 优先释放request 会降低内存峰值
                request.Dispose();
            }
        }
    }

    // 下载图片
    private IEnumerator DoLoadTexture() {
        string url = Application.streamingAssetsPath + "/" + "test.png";
        using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(url)) {
            yield return request.SendWebRequest();
            if (request.isHttpError || request.isNetworkError) {
                // 下载出错
                print(request.error);
            } else {
                // 下载完成
                Texture2D texture = (request.downloadHandler as DownloadHandlerTexture).texture;
                // 优先释放request 会降低内存峰值
                request.Dispose();
            }
        }
    }

    // 下载AssetBundle
    private IEnumerator DoLoadAssetBundle() {
        string url = Application.streamingAssetsPath + "/" + "test.ab";
        using (UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(url)) {
            yield return request.SendWebRequest();
            if (request.isHttpError || request.isNetworkError) {
                // 下载出错
                print(request.error);
            } else {
                // 下载完成
                AssetBundle assetBundle = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
                // 优先释放request 会降低内存峰值
                request.Dispose();
            }
        }
    }

}

最重要的API

1.UnityWebRequestAssetBundle.GetAssetBundle(url, hash)
通过http下载资源包并直接解压到本地磁盘 解压格式类似于Uncompression格式。
PC路径为:C:\Users\{UserName}\AppData\LocalLow\Unity\{CompanyName}_{ProductName}\{BundleName}\{Hash}\

2.AssetBundle.LoadFromFileAsync(url)
通过Url异步加载本地资源包,这是读取本地资源包最好的方法,速度也非常快。不建议用LoadFromFile() 虽然速度最快,但是阻塞主进程,影响体验。

3.AssetBundle.LoadFromMemoryAsync(bytes)
通过byte[]异步加载本地资源包,用来读取加密的资源包。注意资源包会完全缓存进内存中,内存占用巨大,少用。

4.AssetBundle.RecompressAssetBundleAsync(fromUrl, toUrl, compression)
注:Unity 2018.3新增API
可以把资源包重新压缩为Uncompression或LZ4格式,这下资源包的格式完全变得可控了,可以应用更多策略处理资源包。

以上4个API处理资源包完全够用了,剩下的就是一个http下载API

5.UnityWebRequest.Get(url)
通过http下载二进制文件到内存,可以通过File.WriteAllBytes(url, bytes)保存到本地,下载资源包或其他文件可以用这个。(这个并不是下载远程文件最好的API,因为不支持直接下载到本地磁盘,也不支持断点续传,如果要严格控制内存,可以考虑引入其他http插件实现)

官方文档1:
https://docs.unity3d.com/2018...

官方文档2:
https://docs.unity3d.com/Scri...
同步地从磁盘上的文件加载一个资源包。
该函数支持任何压缩类型的包。
在lzma压缩格式下,数据将被解压到内存中。未压缩格式和块压缩格式可以直接从磁盘读取。
与LoadFromFileAsync相比,这个版本是同步的,在创建AssetBundle对象之前不会返回。
这是加载AssetBundle最快的方法。

PS:从官方文档可以看出 似乎不压缩或LZ4要比LZMA性能更好 百度后发现确实如此
LZ4要比LZMA加载速度更快 内存占用更小 但是包体积稍大一些

参考资料:
《关于LZMA和LZ4压缩的疑惑解析》https://blog.csdn.net/weixin_...
《同样的场景,分别用LZMA和LZ4压缩方式,通过AssetBundle.LoadFromFile(Async)加载,内存上可以相差多少》
https://answer.uwa4d.com/ques...
《AssetBundleCompression Bundle的压缩格式》http://blog.sina.com.cn/s/blo...

各API加载测试:
先说结论:当使用无压缩和LZ4压缩格式时,加载速度极快,内存占用很小,lz4居然比无压缩还要快,有点意外,本以为无压缩会更快的。
当使用LZMA格式时,加载时间急剧增加,内存上升急剧增加,相当于在内存里完全缓存一个未压缩格式的资源包。

AssetBundle.LoadFromFileAsync(url)本地加载测试:

压缩格式包体积加载时间内存上升
No50.1M17ms左右1M左右
LZ448.5M10ms左右1M左右
LZMA41.7M2400ms左右51M左右

各API加载测试:
测试资源包:test.ab 未压缩:50.1M LZ4压缩: 48.5M LZMA压缩:41.7M

压缩格式:LZ4 大小:48.5M 测试平台:PC 本地文件

API加载时间内存上升说明
new WWW(path)48ms49M排除误差 内存基本与资源体积一致
UnityWebRequest.Get(path)48ms49M排除误差 内存基本与资源体积一致
UnityWebRequest.GetAsssetBundle(path)96ms1M第一次需要下载并解压 缓存到本地
UnityWebRequest.GetAsssetBundle(path)12ms1M第二次开始 加载速度很快 内存很小
AssetBundle.LoadFromFile(path)3ms1.1M加载速度最快 内存很小 只缓存索引
AssetBundle.LoadFromFileAsync(path)18ms0.8M加载速度极快 内存最小 异步版LoadFromFile
AssetBundle.LoadFromMemory(path)78ms52M缓存解压后的资源 内存占用最大
AssetBundle.LoadFromMemoryAsync(path)91ms51M缓存解压后的资源 异步版LoadFromMemory

压缩格式:LZMA 大小:41.7M 测试平台:PC 本地文件

API加载时间内存上升说明
new WWW(path)32ms42M排除误差 内存基本与资源体积一致
UnityWebRequest.Get(path)32ms42M排除误差 内存基本与资源体积一致
UnityWebRequest.GetAsssetBundle(path)2465ms1M第一次需要下载并解压 缓存到本地
UnityWebRequest.GetAsssetBundle(path)12ms1M第二次开始 加载速度很快 内存很小
AssetBundle.LoadFromFile(path)2244ms52M加载速度慢 内存最大 缓存解压后的资源
AssetBundle.LoadFromFileAsync(path)2387ms51M加载速度最慢 内存很大 异步版LoadFromFile
AssetBundle.LoadFromMemory(path)2249ms52M缓存解压后的资源 内存占用最大
AssetBundle.LoadFromMemoryAsync(path)2377ms51M缓存解压后的资源 异步版LoadFromMemory

总结:
多看官方更新日志,多看官方样例,多看官方文档,熟悉官方API才能更好的掌控性能。
如果对资源包的处理比较复杂,需要自己定制资源包生成器和加载器。
注意资源包的压缩格式和加载API,对性能影响非常大。
LZMA:高压缩、低性能、高内存、体积最小格式。
LZ4 :中压缩、高性能、低内存、性价比最高格式。
两者性能差距非常大,使用LZMA加载巨慢,要特别注意。

LZMA和LZ4该如何选择呢?
小孩子才做选择题,成年人当然是全都要!既要高压缩,体积小的文件格式,又要加载速度快,内存小的性能优势,
高压缩和高性能要兼顾,可以考虑用高压缩格式传输文件,解压为低压缩格式后后保存到本地,用本地加载API提高速度。
WWW.LoadFromCacheOrDownload()和UnityWebRequest.GetAsssetBundle()提供的就是这个功能,推荐使用后者。

Unity 2018.3新增API提供了转换资源包压缩格式的功能,这样可以用zip或其他高压缩格式下载文件,解压后用API转换为LZ4格式高速读取,可以做到最小下载体积和最快加载速度兼顾,就是实现起来需要一些时间处理细节。

参考资料:
《Unity Assetbundle的加载方式的效率和内存占用》https://blog.csdn.net/u012740...
《WWW.LoadFromCacheOrDownLoad官方文档》https://docs.unity3d.com/2018...
《UnityWebRequest.GetAssetBundle官方文档》https://docs.unity3d.com/2018...

转载请标明原文地址:https://segmentfault.com/a/11...

 

 

 

 

 

相关文章:

  • Unity开发(三) AssetBundle同步异步引用计数资源加载管理器
  • Unity脚本运行时更新带来了什么?
  • UE4 补丁更新(基于Http)
  • UE4 Pak加载
  • Unity3D Shader加载时机和预编译
  • ShaderVariantCollection解决shader_feature丢失
  • 一次UNITY闪退问题的定位心得
  • Unity AssetBundle打包 , BuildAssetBundleOptions
  • protobuf-net 的应用
  • Using Unity’s ShaderVariantCollection
  • Unity技术分享连载(64)|Shader Variant Collection|Material.SetPassFast
  • 最新的asmdef定义的模块中,VisualStudio中无法引用UnityEngine.iOS.XCode命名空间
  • UNIYT关于V S2017,VS2019断点调试卡住的问题
  • Mac上用VS Code调试 Unity程序
  • Jenkins的Credentials(证书)管理
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • create-react-app项目添加less配置
  • express + mock 让前后台并行开发
  • Go 语言编译器的 //go: 详解
  • Java多线程(4):使用线程池执行定时任务
  • Java精华积累:初学者都应该搞懂的问题
  • select2 取值 遍历 设置默认值
  • 经典排序算法及其 Java 实现
  • 我是如何设计 Upload 上传组件的
  • 移动端唤起键盘时取消position:fixed定位
  • 走向全栈之MongoDB的使用
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • #define、const、typedef的差别
  • #图像处理
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (Ruby)Ubuntu12.04安装Rails环境
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (七)c52学习之旅-中断
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .Net Web项目创建比较不错的参考文章
  • .NET序列化 serializable,反序列化
  • .NET运行机制
  • .Net中wcf服务生成及调用
  • .NET中的十进制浮点类型,徐汇区网站设计
  • .sys文件乱码_python vscode输出乱码
  • @angular/cli项目构建--http(2)
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • @property @synthesize @dynamic 及相关属性作用探究
  • @Repository 注解
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [ solr入门 ] - 利用solrJ进行检索
  • [.net]官方水晶报表的使用以演示下载
  • [AutoSar NVM] 存储架构
  • [AutoSar]BSW_Com02 PDU详解