【Unity】AssetBundles浅析

是什么

AssetBundle是包含模型、材质、纹理、场景等资源的文件。是把unity资源按照一定的规则打包,然后这些资源可以上传的服务器,在游戏中可以下载这些资源,再把解包成资源。


打包上传服务器

分为两步:1.打包AssetBundles。2.上传AssetBundles到服务起。


下载解包

分为两步:1.下载AssetBundles到应用中。2.加载需要的资源从AssetBundles

怎么用

步骤在上面的介绍都可以清晰的看出来了,我们这里分为5个简单的步骤。

简单的工作流:
●在编辑器中组织和设置AssetBundles。
●打包AssetBundles。
●上传AssetBundles到外部存储。
●在运行时下载AssetBundles。
●加载AssetBundles中的资源。

下面我们来详细的看看每一个步骤具体怎么做。

在编辑器中组织和设置AssetBundles:

这里只需要设置名字与类别。



先在AssetBundle设置资源的AssetBundle的名字。这里这里设置名字时,设置二级菜单使用/斜杠编写名字例如environment/desert.


Paste_Image.png

名字后面还可以设置一个类别,叫作AssetBundle Variants,跟shader里面设置不同设备渲染算法不同一个道理,这个设置名称来区别加载那里一资源。比如说在好一点设备上可以加载高模不卡顿,而差一点的设备中只能加载低模才不卡顿,我们就可以使用这个来区别。这个也可用来做分包,不同版本包,最好的例子就是做多语言包。

打包AssetBundles:
然后再导出AssetBundle使用下面的代码。

  [MenuItem("Assets/Build AssetBundles")]
  private static void BuildAllAssetBUndles()
  {
      BuildPipeline.BuildAssetBundles("Assets/AssetBundles", BuildAssetBundleOptions.None,
        BuildTarget.StandaloneOSXUniversal);
  }

值得注意的是这里导出的路径是必须存在的,也就是这里的第一个参数。

第二个参数是可以设置压缩方式的,这里看看压缩有那些。
Asset Bundle 压缩分为三种:
1.LZMA:默认的压缩方式,特点是可以达到很小的容量,但是这样就会导致解压时会花更多的时间。设置为BuildAssetBundleOptions.None,作为DLCs的资源用这种压缩。
2.LZ4:5.3版本之后才有,压缩出来还是比较大容量,但是在加载使用时,不需要去解压缩,只需要校对一下即可。设置为BuildAssetBundleOptions.ChunkBasedCompression,加密资源,配置表,资源流等这些使用这种压缩。
3.不压缩:原始大小,加载快。设置为BuildAssetBundleOptions.UncompressedAssetBundle
当然还可以在这里设置一个条件,比如说不包含属性信息打包等。

第三个参数也就是设置打包到那个目标机型上去。

这里会生成两类文件,一个是Manifest,有一点像配置表的意思,它存储了打包资源的依赖文件的信息。这个依赖跟我们在unity中导出package包是一样的,他会把这个资源用到的其他资源记录下来。

在运行时下载AssetBundles:

这里有3种方式下载AssetBundles,通过名字我们就可以知道他们的区别:
1.无缓存:使用的是WWW object,也就是说使用的new WWW对象。例子如下:

    using System;
    using UnityEngine;
    using System.Collections; class NonCachingLoadExample : MonoBehaviour {
    public string BundleURL;
    public string AssetName;
    IEnumerator Start() {
        // Download the file from the URL. It will not be saved in the Cache
        using (WWW www = new WWW(BundleURL)) {
            yield return www;
            if (www.error != null)
                throw new Exception("WWW download had an error:" + www.error);
            AssetBundle bundle = www.assetBundle;
            if (AssetName == "")
                Instantiate(bundle.mainAsset);
            else
                Instantiate(bundle.LoadAsset(AssetName));
                    // Unload the AssetBundles compressed contents to conserve memory
                    bundle.Unload(false);

        } // memory is freed from the web stream (www.Dispose() gets called implicitly)
    }
    }

2.有缓存:使用的是WWW.LoadFromCacheOrDownload。使用这个至少用4GB。

using System;
using UnityEngine;
using System.Collections;

public class CachingLoadExample : MonoBehaviour {
public string BundleURL;
public string AssetName;
public int version;

void Start() {
    StartCoroutine (DownloadAndCache());
}

IEnumerator DownloadAndCache (){
    // Wait for the Caching system to be ready
    while (!Caching.ready)
        yield return null;

    // Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
    using(WWW www = WWW.LoadFromCacheOrDownload (BundleURL, version)){
        yield return www;
        if (www.error != null)
            throw new Exception("WWW download had an error:" + www.error);
        AssetBundle bundle = www.assetBundle;
        if (AssetName == "")
            Instantiate(bundle.mainAsset);
        else
            Instantiate(bundle.LoadAsset(AssetName));
                // Unload the AssetBundles compressed contents to conserve memory
                bundle.Unload(false);

    } // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
}

3.使用UnityWebRequest,这个可以取代www来使用,具体写法:

      //string uri = @"file:///E:\Unity Project Workspace\AssetBundleProject\AssetBundles\cubewall.unity3d";
    string uri = @"http://localhost/AssetBundles/cubewall.unity3d";
    UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri);
    yield return request.Send();
    //这里可以使用两种方式来获得AssetBundle 
    //AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
    AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
    
    //使用里面的资源
    GameObject wallPrefab = ab.LoadAsset<GameObject>("CubeWall");
    Instantiate(wallPrefab);

加载AssetBundles中的资源:

资源下载来了,这里像是Resource.Load的用法。我们可以使用三个方式来加载资源:

●AssetBundle.LoadAsset:直接加载
●AssetBundle.LoadAssetAsync:异步加载
●AssetBundle.LoadAllAssets:加载所有

这里的异步加载需要在加载大量资源或者资源容量大的时候使用。

这里有一个AssetBundle.Unload方法,是用来释放内存的,这个方法需要传入一个bool值,如果传入的是FALSE,这个AssetBundle就会被消除,但是从这个AssetBundle中加载出来的资源不会被删除。传入TRUE的话加载出来的资源也会被消除。在后面也可以使用Resource.UnLoadUnuseAssetBundle来卸载。

这里如果是依赖打包的,需要先加载共享资源包,然后再加载使用这个资源的预制物体这些。 这个加载顺序无所谓,但是在使用预制物体时,资源是要先加载出来的。这里的加载就是实例化出一个assetbundle对象。

我们可以直接加载总的生成的AssetBundles文件,再通过这个文件获得AssetBundleManifest依赖文件,获得这个打包文件的所有文件名字,然后根据名字来加载这个包里的文件。

    var manifestAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
    var manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

    foreach (var name in manifest.GetAllAssetBundles())
    {
        print(name);
    }
    string[] strs = manifest.GetAllDependencies("cubewall.unity3d");
    foreach (string name in strs)
    {
        print(name);
        AssetBundle.LoadFromFile("AssetBundles/" + name);
    }

相关小记

分包策略
这里就是设置AssetBundle Variants这个,一些小策略有这些:
1.根据文件类型来分包,比如:贴图、声音这样的分类。
2.根据场景来分包,每有一个场景都设置一个包单独来控制。
3.根据物体的整理来分包,比如一个UI界面的预制体,这个预制体上用到的图片、脚本、shader等都打包在一起。
4.经常更新的资源放在一个包,不经常更新的资源放在一个包。
5.把共享资源打包成单独的包,这个也就是以来打包。

储存小原理

存储文件系统的结构

压缩区域指的是了chunk-base压缩(LZ4)或者stream-base压缩(LZMA)。
LZ4就是把资源平均分成很多个数据块,然后再把每个数据块单独压缩。使用这种压缩的话就是可以在运行时读取随机的数据消耗会很小,个人理解这里用这种压缩方式的一般是数据表之类的。
LZMA就是尽可能的压缩资源,但是读取的话只能序列读取。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容