精华内容
下载资源
问答
  • Unity 加载AssetBundle

    2020-04-09 11:34:09
    Unity 加载AssetBundle https://segmentfault.com/a/1190000019656656 随着Unity版本的更新,加载AssetBundle的API也在不断变化,熟悉这些API才获得更好的性能,在这里对加载方式做个整理与总结。 WWW (官方已...

    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)本地加载测试:

    压缩格式 包体积 加载时间 内存上升
    No 50.1M 17ms左右 1M左右
    LZ4 48.5M 10ms左右 1M左右
    LZMA 41.7M 2400ms左右 51M左右

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

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

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

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

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

    千次阅读 2018-09-25 14:58:38
    使用版本 Unity2017.4.10 --- Vs2017 ---- Windows7 忘记加上一句,使用IIS搭建FTP的时候,别设置登录限制 LZMA压缩-&gt;YuSongMomo-&gt;https://www.xuanyusong.com/archives/3095 --------------------...

    使用版本 Unity2017.4.10 --- Vs2017 ---- Windows7

    忘记加上一句,使用IIS搭建FTP的时候,别设置登录限制

    LZMA压缩->YuSongMomo->https://www.xuanyusong.com/archives/3095

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------

          读取路径为:

    ftp://127.0.0.1:10091//StreamingAssets/PC/PC.manifest

          Tag为:prefab,image,material,依赖关系如下

    总的Manifest如下:

    其中,prefab.asset里面只有一个Cube,这个Cube的材质是引用image里面的一张图片

    image manifest:

    prefab manifest:

    打包代码:

    using UnityEditor;
    
    public class BuildAssetBundle : Editor {
        [MenuItem("Build/PC")]
        public static void BuildPC()
        {
            BuildPipeline.BuildAssetBundles("Assets/StreamingAssets/PC",BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows64);
        }
        [MenuItem("Build/Android")]
        public static void BuildAndroid()
        {
            BuildPipeline.BuildAssetBundles("Assets/StreamingAssets/Android",BuildAssetBundleOptions.None,BuildTarget.Android);
        }
    }
    

    加载代码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class LoadWWW : MonoBehaviour
    {
    
        void Start()
        {
            // 服务器地址,加载的包名(你打包到某个文件夹下,就会有一个对应的文件夹的manifest文件),版本号
            StartCoroutine(LoadManifest("ftp://127.0.0.1:10091/StreamingAssets/PC/", "PC", 1));  
        }
    
        /// <summary>
        /// 加载所有依赖
        /// </summary>
        /// <param name="path"></param>
        /// <param name="filename"></param>
        /// <param name="version"></param>
        /// <returns></returns>
        IEnumerator LoadManifest(string path, string filename, int version)
        {
            WWW www = new WWW(path + filename);  // 加载路径
            yield return www; // 等待加载完成
            // 如果错误不为空,这里其实应该return,但是我宁愿看见详细的报错,也不想只有一个Debug
            if (www.error != null) 
            {
                Debug.Log(www.error);
            }
            AssetBundle ab = www.assetBundle;
            AssetBundleManifest manifestName = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); // 获得Manifest里面的依赖
            ab.Unload(false); // 写在相应包,注意别写True,下面会解释
            www.Dispose();
            string[] abName = manifestName.GetAllAssetBundles();  // 遍历所有AssetBundle名字
            foreach (var item in abName)
            {
                if (item == "prefab")
                    StartCoroutine(LoadPrefab(path, item, version));
                else
                    StartCoroutine(LoadPrefab(path, item, version,false));
            }
            yield return null;
        }
    
        /// <summary>
        /// 加载AssetBundle里面所有的Prefab
        /// </summary>
        /// <param name="path"></param>
        /// <param name="filename"></param>
        /// <param name="version"></param>
        /// <returns></returns>
        IEnumerator LoadPrefab(string path, string filename, int version, bool IsLoad = true)
        {
            WWW www = WWW.LoadFromCacheOrDownload(path + filename,version); // 将这个包缓存下载,下次再次加载的时候version不变,就不会重新从网络上下载
            yield return www;  // 等待下载OR加载完成
            if (www.error != null) // 如果报错信息不为空
                Debug.Log(www.error);
            AssetBundle asbundle = www.assetBundle; // 获得包
            foreach (var item in asbundle.GetAllAssetNames()) // 遍历包中的所有项
            {
                GameObject obj = asbundle.LoadAsset<GameObject>(item); // 加载
                if (IsLoad)  // 我们包里面有图片和材质,这两个不能生成实例
                    Instantiate<GameObject>(obj);
            }
        }
    
    }
    

           下面是对于Start里面三个参数的图片,那坨马赛克是127.0.0.1(估计你们也不信 Hah) ftp://XXX:端口//文件夹名字//文件名

    之后运行,当,就会发现出现了一只Cube,去掉头营养贼高

     

     

    展开全文
  • unity 加载assetbundle

    2017-03-27 14:46:42
    简单的版本 (assetsbundle 的加载)  IEnumerator starts()  {  using (WWW WWW = new WWW(url))  {  yield return WWW; // 等待网络数据加载完成  if (WWW.error != null)

    简单的版本  (assetsbundle  的加载)

      IEnumerator starts()

        {
            using (WWW WWW = new WWW(url))
            {
                yield return WWW;   //   等待网络数据加载完成  


                if (WWW.error != null)
                {
                    Debug.LogError("网络数据错误");
                }
                else
                {
                    AssetBundle assets = WWW.assetBundle;
                    //   加载资源    预制体的    名字
                    if (assets != null)
                    {
                        Object obj = assets.LoadAsset(assetsname);

                        Instantiate(obj);
                    }


                
                }
            }
    展开全文
  • 加载AssetBundle的方法1,从二进制文件中异步加载AB2,资源同步加载3,从文件中进行直接加载4,从文件中进行异步加载5,网页加载 UnityWebRequest(一)6,网页加载 UnityWebRequest(二)7,网页加载 Unity...

    1,从二进制文件中异步加载AB

    IEnumerator LoadAB()
    {
      AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
      yield return request;
      AssetBundle ab = request.assetBundle;
      GameObject monster = ab.LoadAsset<GameObject>("Monster");
      Instantiate(monster);
    }
    

    2,资源同步加载

    Instantiate(AssetBundle.LoadFromMemory(File.ReadAllBytes(path)).LoadAsset<GameObject>("Monster"));
    

    3,从文件中进行直接加载

    AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/scene/monster.ab");
    GameObject monster= ab.LoadAsset<GameObject>("Monster");
    Instantiate(monster);
    

    4,从文件中进行异步加载

    IEnumerator LoadCacheOrDownloadFromFile(string path)
    {
      WWW www = WWW.LoadFromCacheOrDownload(path, 1);
      yield return www;
    
      if( !string.IsNullOrWhiteSpace(www.error) )
      {
        Debug.Log(www.error);
        yield break;
      }
      AssetBundle ab = www.assetBundle;
      GameObject monster = ab.LoadAsset<GameObject>("Monster");
      Instantiate(monster);
    }
    

    5,网页加载 UnityWebRequest(一)

    UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(path);
    yield return request.SendWebRequest();
    AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
    GameObject monster = ab.LoadAsset<GameObject>("Monster");
    Instantiate(monster);
    

    6,网页加载 UnityWebRequest(二)

    UnityWebRequest request = UnityWebRequest.Get(path);
    request.downloadHandler = new DownloadHandlerAssetBundle (path, 0);
    yield return request.SendWebRequest();
    AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
    GameObject monster = ab.LoadAsset<GameObject>("Monster");
    Instantiate(monster);
    

    7,网页加载 UnityWebRequest(三)

    UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(path);
    yield return request.SendWebRequest();
    AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
    GameObject monster = ab.LoadAsset<GameObject>("Monster");
    Instantiate(monster);
    

    8,读取Manifest文件,获取它们的依赖关系并且加载出来

    AssetBundle manifestAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
    AssetBundleManifest manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    string[] strArr = manifest.GetAllDependencies("scene/monster.ab");
    foreach (var item in strArr)
    {
      AssetBundle.LoadFromFile("AssetBundles/" + item);
    }
    
    展开全文
  • 测试时 在Editor下加载Assetbundle文件夹下路径成功 在Android下使用www一直失败 使用Assetbundle.loadfromfile可以  发现:加载Assetbundle文件 使用AssetBundle.LoadFromFile的路径是path,那么使用www加载需要...
  • 最近整理了Unity中关于AssetBundle加载方式的整理,代码如下 using System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Networking; ...
  • https://www.cnblogs.com/kanekiken/p/7851685.html https://www.tuicool.com/articles/ieYJBf  IEnumerator AA()  {  //=============本地加载可以不用协程==================  //AssetBundle ab = Asset...
  • 结合Unity官网unity Manual 给出关于AssetBundle的一些加载方法,通过简单示例进行学习总结。 使用Unity版本 unity 2018.4.1 ,其中官网中介绍关于UnityWebRequest加载方式在unity2018中的测试是有问题的,经过研究...
  • //用来存放加载出来的依赖资源的AssetBundle string[] dependences = manifest.GetAllDependencies(targetAssetName); Debug.Log("依赖文件个数:" + dependences.Length); int length = dependences.Length; ...
  • Unity 加载AssetBundle中AB包的几种方式

    万次阅读 2018-03-20 15:29:00
    unity中创建一个Cube,设置成预制体,生成AssetBundle中AB包,生成包代码如下: BuildPipeline.BuildAssetBundles(dir,BuildAssetBundleOptions.None ,BuildTarget.StandaloneWindows64);参数分别为:地址,压缩...
  • Unity加载AssetBundle后shader丢失问题

    千次阅读 2017-05-09 12:57:54
    解决办法: 1 把shader文件放入...2 在程序中 通过Resources加载这个shader,然后再赋给某个物体 gameObject.GetComponent().material.shader = Resources.Load("shuangmian");FR:海涛高软(QQ技术交流群:386476712)
  • unity使用UnityWebRequest加载AssetBundle

    千次阅读 2020-04-30 19:52:50
    unity加载AssetBundle包并显示进度条 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; public class ABTest : ...
  • Unity5 AssetBundle 加载

    千次阅读 2018-01-22 16:13:40
    Unity5 AssetBundle 加载 上一篇说了 AssetBundle 打包 本篇接着做加载 加载需要考虑的两个问题: 一、如何将资源加载 二、资源依赖的其他资源如何处理 理论:一个预设 A 依赖 一个材质球B、一个材质球 C、 ...
  • 关于unityAssetbundle动态加载,刚刚在网上学了一点,现在就分享给大家,亲测有用
  • Unity3D 简单的AssetBundle打包与加载 转载:Unity AssetBundle 从入门到掌握(适合初学者) 简单AssetBundle打包与加载问题总结
  • Unity5 AssetBundle 打包以及加载

    千次阅读 2016-12-16 23:00:49
    Unity5 AssetBundle打包以及加载 关于AssetBundle 是什么,干什么用,在网上到处是,在此就不过多赘述了。下面直接上代码,如何打包 AssetBundle,打包的AB如何加载。 打包AB using UnityEngine; using System....
  • unityassetbundle加载

    2017-12-04 17:42:06
    最近在写assetbundle的编辑器,顺便写了一下unity的资源管理器。 研究了一下王者农药的热更新机制,发现它的首页动画界面也可以热更新,但是这个时候才在启动进度条界面。 猜想了1下,他的资源加载路径是变化的。 ...
  • AssetBundle的加载与卸载方式摘要 ...用于加载AssetBundle的API AssetBundle.LoadFromFile[Async]() 首选方法(在速度、磁盘使用和内存占用方面都很高效) 适用于从本地存储加载未压缩或LZ4压缩的AssetBundle...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,586
精华内容 2,634
关键字:

unity加载assetbundle