Unity資源打包之Asset Bundle

Asset Bundle的作用:
1.AssetBundle是一個(gè)壓縮包包含模型、貼圖、預(yù)制體、聲音、甚至整個(gè)場(chǎng)景,可以在游戲運(yùn)行的時(shí)候被加載;
2.AssetBundle自身保存著互相的依賴關(guān)系;
3.壓縮包可以使用LZMA和LZ4壓縮算法,減少包大小,更快的進(jìn)行網(wǎng)絡(luò)傳輸;
4.把一些可以下載內(nèi)容放在AssetBundle里面,可以減少安裝包的大??;
什么是AssetBundle
可以歸為兩點(diǎn):
1,它是一個(gè)存在于硬盤上的文件??梢苑Q之為壓縮包。這個(gè)壓縮包可以認(rèn)為是一個(gè)文件夾,里面包含了多個(gè)文件。這些文件可以分為兩類:serialized file 和 resource files。(序列化文件和源文件)
serialized file:資源被打碎放在一個(gè)對(duì)象中,最后統(tǒng)一被寫進(jìn)一個(gè)單獨(dú)的文件(只有一個(gè))
resource files:某些二進(jìn)制資源(圖片、聲音)被單獨(dú)保存,方便快速加載
2,它是一個(gè)AssetBundle對(duì)象,我們可以通過(guò)代碼從一個(gè)特定的壓縮包加載出來(lái)的對(duì)象。這個(gè)對(duì)象包含了所有我們當(dāng)初添加到這個(gè)壓縮包里面的內(nèi)容,我們可以通過(guò)這個(gè)對(duì)象加載出來(lái)使用。

Asset Bundle資源打包實(shí)例

無(wú)論是模型資源還是UI資源,最好是先把他們放在Prefab中,然后在做成Assetbundle。我們以模型來(lái)舉例,Assetbundle中可以放一個(gè)模型、也可以放多個(gè)模型,它是非常靈活了那么最需要考慮的就是模型空間占用的問(wèn)題。

下面我們來(lái)實(shí)際操作下,首先隨便先創(chuàng)建兩個(gè)3D對(duì)象,Cube和Capsule,并將他們做成Prefab,然后去指定資源的AssetBundle屬性,這里我將這兩個(gè)模型都打包成model.ab包
(xxxa/xxx)這里xxxa會(huì)生成目錄,名字為xxx ,后面的ab是后綴名,可自己制定。


Paste_Image.png

設(shè)置好屬性后,下面開(kāi)始構(gòu)建AssetBundle包,首先先創(chuàng)建一個(gè)文件夾命名Editor,這個(gè)文件夾是不會(huì)進(jìn)行打包的特定編輯器擴(kuò)展文件夾。然后我們創(chuàng)建一個(gè)編輯器擴(kuò)展類CreateAssetbundles。寫入下面的代碼

using UnityEditor;
using System.IO;

public class CreateAssetbundles  {

    [MenuItem("AssetsBundle/Build AssetBundles")]
     static void BuildAllAssetBundles()//進(jìn)行打包
    {
        string dir = "AssetBundles";
        //判斷該目錄是否存在
        if (Directory.Exists(dir) == false)
        {
            Directory.CreateDirectory(dir);//在工程下創(chuàng)建AssetBundles目錄
        }
        //參數(shù)一為打包到哪個(gè)路徑,參數(shù)二壓縮選項(xiàng)  參數(shù)三 平臺(tái)的目標(biāo)
        BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows64);
    }
}

BuildAssetBundleOptions.None:使用LZMA算法壓縮,壓縮的包更小,但是加載時(shí)間更長(zhǎng)。使用之前需要整體解壓。一旦被解壓,這個(gè)包會(huì)使用LZ4重新壓縮。使用資源的時(shí)候不需要整體解壓。在下載的時(shí)候可以使用LZMA算法,一旦它被下載了之后,它會(huì)使用LZ4算法保存到本地上。
BuildAssetBundleOptions.UncompressedAssetBundle:不壓縮,包大,加載快
BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4壓縮,壓縮率沒(méi)有LZMA高,但是我們可以加載指定資源而不用解壓全部。
注意使用LZ4壓縮,可以獲得可以跟不壓縮想媲美的加載速度,而且比不壓縮文件要小。

然后回到Unity里面點(diǎn)擊我們剛剛擴(kuò)展出來(lái)的打包按鈕

Paste_Image.png

點(diǎn)擊后我們的模型就打包了出來(lái),可以在工程的目錄下可以找到AssetBundles目錄,在AssetBundles下有個(gè)Scene文件夾里面就是我們的打包文件了,后綴是.ab


Paste_Image.png

AssetBundle的加載

AssetBundle的加載有以下幾種方式,從內(nèi)存加載使用LoadFromMemoryAsync,從本地文件加載可以使用LoadFromFile,從服務(wù)器上Web上加載可以使用UnityWbRequest。下面我們來(lái)看看這幾種加載的方式。
首先可以先把我們Unity里面的兩個(gè)模型的Prefab Cube和Capsule刪除了,然后創(chuàng)建一個(gè)腳本掛在Camera上,打開(kāi)腳本
第一種加載方式(LoadFromMemoryAsync)從內(nèi)存加載

using UnityEngine;
using System.IO;
using System.Collections;
public class LoadFromFileExample : MonoBehaviour {

    IEnumerator  Start () {
        string path = "AssetBundles/scene/model.ab";
        //第一種加載AB的方式 LoadFromMemoryAsync
        //異步加載
        AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
        yield return request;
        AssetBundle ab = request.assetBundle;
        //同步方式
        //AssetBundle ab=  AssetBundle.LoadFromMemory(File.ReadAllBytes(path));

         //使用里面的資源
        Object[] obj = ab.LoadAllAssets<GameObject>();//加載出來(lái)放入數(shù)組中
        // 創(chuàng)建出來(lái)
        foreach (Object o in obj)
        {
            Instantiate(o);
        }
    }
}

第二種方式(LoadFromFile)從本地加載

using UnityEngine;
using System.Collections;

public class LoadFromFileExample : MonoBehaviour {

    IEnumerator  Start () {
        string path = "AssetBundles/scene/model.ab";
        //第二種加載方式 LoadFromFile
        //異步加載
        AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(path);
        yield return request;
        AssetBundle ab = request.assetBundle;
        //同步加載
        //AssetBundle ab = AssetBundle.LoadFromFile(path);

        //使用里面的資源
      Object[] obj = ab.LoadAllAssets<GameObject>();//加載出來(lái)放入數(shù)組中
        // 創(chuàng)建出來(lái)
        foreach (Object o in obj)
        {
            Instantiate(o);
        }
     }
}

第三種方式(UnityWbRequest)從服務(wù)器或者本地加載

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

public class LoadFromFileExample : MonoBehaviour {

    IEnumerator  Start () {
        //第三種加載方式   使用UnityWbRequest  服務(wù)器加載使用http本地加載使用file
        //string uri = @"file:///C:\Users\Administrator\Desktop\AssetBundleProject\AssetBundles\model.ab";
        string uri = @"http://localhost/AssetBundles\model.ab";
        UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri);
        yield return request.Send();
        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);

        //使用里面的資源
      Object[] obj = ab.LoadAllAssets<GameObject>();//加載出來(lái)放入數(shù)組中
        // 創(chuàng)建出來(lái)
        foreach (Object o in obj)
        {
            Instantiate(o);
        }
    }
}

這樣我們Model包里面的資源就加載出來(lái)并創(chuàng)建在場(chǎng)景里了。這時(shí)候運(yùn)行Unity就可以看到兩個(gè)模型都各自創(chuàng)建了出來(lái)


Paste_Image.png

當(dāng)然也可以創(chuàng)建指定的資源例如


      AssetBundle ab=AssetBundle.LoadFromFile("AssetBundles/scene/model.ab");
        GameObject go = ab.LoadAsset<GameObject>("Cube");
        Instantiate(go)

這樣就實(shí)現(xiàn)了Asset Bundle資源的加載了

AssetBundle分組策略

1,把經(jīng)常更新的資源放在一個(gè)單獨(dú)的包里面,跟不經(jīng)常更新的包分離
2,把需要同時(shí)加載的資源放在一個(gè)包里面
3,可以把其他包共享的資源放在一個(gè)單獨(dú)的包里面
4,把一些需要同時(shí)加載的小資源打包成一個(gè)包
5,如果對(duì)于一個(gè)同一個(gè)資源有兩個(gè)版本,可以考慮通過(guò)后綴來(lái)區(qū)分 v1 v2 v3 unity3dv1 unity3dv2

1,邏輯實(shí)體分組
a,一個(gè)UI界面或者所有UI界面一個(gè)包(這個(gè)界面里面的貼圖和布局信息一個(gè)包)
b,一個(gè)角色或者所有角色一個(gè)包(這個(gè)角色里面的模型和動(dòng)畫一個(gè)包)
c,所有的場(chǎng)景所共享的部分一個(gè)包(包括貼圖和模型)
2,按照類型分組
所有聲音資源打成一個(gè)包,所有shader打成一個(gè)包,所有模型打成一個(gè)包,所有材質(zhì)打成一個(gè)包
3,按照使用分組
把在某一時(shí)間內(nèi)使用的所有資源打成一個(gè)包??梢园凑贞P(guān)卡分,一個(gè)關(guān)卡所需要的所有資源包括角色、貼圖、聲音等打成一個(gè)包。也可以按照?qǐng)鼍胺?,一個(gè)場(chǎng)景所需要的資源一個(gè)包

依賴打包

意思就是例如有兩個(gè)模型使用的都是同一個(gè)材質(zhì)和貼圖,那么模型和材質(zhì)貼圖之間就是依賴關(guān)系。如果我們這兩個(gè)模型都單獨(dú)打包出來(lái)那么就會(huì)打包出兩份材質(zhì)和貼圖,這樣包就會(huì)變大,那么我們?nèi)绾谓鉀Q呢,這里Unity里面自帶有一種方式,那就是首先先把所依賴的材質(zhì)和貼圖單獨(dú)打包到一個(gè)文件夾中,然后再分別打包兩個(gè)需要依賴這個(gè)材質(zhì)和貼圖的模型。這樣Unity就會(huì)去查找這個(gè)材質(zhì)貼圖,發(fā)現(xiàn)這個(gè)材質(zhì)和貼圖已經(jīng)打包了出來(lái),那么它就不會(huì)去重復(fù)的打包材質(zhì)和貼圖了,這樣就大大減小了包的大小


Paste_Image.png

上面一個(gè)是直接兩個(gè)模型分別打包出來(lái)可以看到材質(zhì)和貼圖都分別打包了出來(lái),分別都是63KB,而下面的是先將材質(zhì)和貼圖打包出來(lái)是62KB再將兩個(gè)2KB的模型打包出來(lái),總共也才64KB。


Paste_Image.png
這就是Unity自帶的依賴打包.
但是加載的時(shí)候模型、材質(zhì)和貼圖都要進(jìn)行去加載,不然就會(huì)出現(xiàn)財(cái)政的丟失
using UnityEngine;

public class LoadFromFileExample : MonoBehaviour {

    void Start () {
        AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/cube.ab");
        AssetBundle abShare = AssetBundle.LoadFromFile("AssetBundles/share.ab");
        //GameObject go = ab.LoadAsset<GameObject>("Cube");
        //Instantiate(go);
        Object[] obj = ab.LoadAllAssets<GameObject>();//加載出來(lái)放入數(shù)組中
        //創(chuàng)建出來(lái)
        foreach (Object o in obj)
        {
            Instantiate(o);
        }
    }
}

使用AssetBundleManifest獲取所有的包
在打包AssetBundle后出現(xiàn)一個(gè)AssetBundles和一個(gè)AssetBundles.manifest兩個(gè)文件,打包出來(lái)的所有的AssetBundle包都會(huì)放在AssetBundles里面。

Paste_Image.png
而AssetBundles.manifest是一個(gè)文本文件,里面有一些包的信息,下面可以打開(kāi)看看
Paste_Image.png
所以下面我們就可以去讀取到AssetBundles然后獲取里面所有的AssetBundle包
在Start方法里面寫入

     AssetBundle manifesAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
        AssetBundleManifest manifest= manifesAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        foreach (string name in manifest.GetAllAssetBundles())
        {
            print(name);
        }

這時(shí)候運(yùn)行Unity就可以看到所有包都完整的輸出出來(lái)了。

Paste_Image.png

利用Manifest加載某個(gè)包所依賴的包

        AssetBundle manifesAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
        AssetBundleManifest manifest= manifesAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        foreach (string name in manifest.GetAllAssetBundles())
        {
            print(name);
        }
        string []strs=manifest.GetAllDependencies("Cube.ab");
        foreach (var name in strs)
        {
            AssetBundle.LoadFromFile("AssetBundles/"+name);
        }

運(yùn)行后可以看到所依賴的Share包的資源也加載了出來(lái)


Paste_Image.png

AssetBundle的卸載

卸載有兩個(gè)方面
1,減少內(nèi)存使用
2,有可能導(dǎo)致丟失
所以什么時(shí)候去卸載資源
AssetBundle.Unload(true)卸載所有資源,即使有資源被使用著
(1,在關(guān)卡切換、場(chǎng)景切換的時(shí)候
(2,資源沒(méi)被調(diào)用的時(shí)候
AssetBundle.Unload(false)卸載所有沒(méi)用被使用的資源
個(gè)別資源怎么卸載
(1,通過(guò) Resources.UnloadUnusedAssets.
(2,場(chǎng)景切換的時(shí)候

文件校驗(yàn)

文件校驗(yàn)可以在文件傳輸?shù)臅r(shí)候保證文件的完整性,例如A在給我傳輸了一個(gè)文件之前會(huì)生成一個(gè)校驗(yàn)碼,對(duì)于這個(gè)文件只會(huì)生成這一個(gè)唯一的校驗(yàn)碼,只要傳輸給我的文件有一點(diǎn)不一樣那么校驗(yàn)碼就會(huì)完全不同。所以A在傳輸給我文件的時(shí)候會(huì)把文件和校驗(yàn)碼都傳輸給我,當(dāng)我取到這個(gè)文件的時(shí)候我也會(huì)使用和A同樣一個(gè)算法去生成這個(gè)文件的校驗(yàn)碼,然后拿這個(gè)值和A傳輸給我的校驗(yàn)碼比對(duì),如果一樣說(shuō)明這個(gè)文件是完整的,如果不一樣那么就重新傳輸。下面是幾個(gè)算法生成的校驗(yàn)值
CRC MD5 SHA1
相同點(diǎn):
CRC、MD5、SHA1都是通過(guò)對(duì)數(shù)據(jù)進(jìn)行計(jì)算,來(lái)生成一個(gè)校驗(yàn)值,該校驗(yàn)值用來(lái)校驗(yàn)數(shù)據(jù)的完整性。
不同點(diǎn):

  1. 算法不同。CRC采用多項(xiàng)式除法,MD5和SHA1使用的是替換、輪轉(zhuǎn)等方法;
  2. 校驗(yàn)值的長(zhǎng)度不同。CRC校驗(yàn)位的長(zhǎng)度跟其多項(xiàng)式有關(guān)系,一般為16位或32位;MD5是16個(gè)字節(jié)(128位);SHA1是20個(gè)字節(jié)(160位);
  3. 校驗(yàn)值的稱呼不同。CRC一般叫做CRC值;MD5和SHA1一般叫做哈希值(Hash)或散列值;
  4. 安全性不同。這里的安全性是指檢錯(cuò)的能力,即數(shù)據(jù)的錯(cuò)誤能通過(guò)校驗(yàn)位檢測(cè)出來(lái)。CRC的安全性跟多項(xiàng)式有很大關(guān)系,相對(duì)于MD5和SHA1要弱很多;MD5的安全性很高,不過(guò)大概在04年的時(shí)候被山東大學(xué)的王小云破解了;SHA1的安全性最高。
  5. 效率不同,CRC的計(jì)算效率很高;MD5和SHA1比較慢。
  6. 用途不同。CRC一般用作通信數(shù)據(jù)的校驗(yàn);MD5和SHA1用于安全(Security)領(lǐng)域,比如文件校驗(yàn)、數(shù)字簽名等。

Unity Asset Bundle Browser tool

這是一個(gè)AssetBundle的查看工具,是Unity官方發(fā)布的一個(gè)擴(kuò)展工具,可以查看幫助打包AssetBundle和查看AssetBundle內(nèi)容??梢匀itHub上下載
https://github.com/Unity-Technologies/AssetBundles-Browser
下載后直接將里面的Editor擴(kuò)展工具拖入我們的Unity Project工程中

Paste_Image.png
然后再窗口Window下找到并選擇AssetBundle Browser選項(xiàng),就可以打開(kāi)看到我們AssetBundle 窗口了
Paste_Image.png

Paste_Image.png
這是一個(gè)輕量級(jí)的AssetsBundle使用工具,里面可以打包可以查看打包的內(nèi)容可以刪除打包的內(nèi)容,非常好用

關(guān)于將AssetBundle上傳到服務(wù)器可以使用FTP上傳工具

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、什么是AssetBundle AssetBundle 是Unity pro提供的一種用來(lái)存儲(chǔ)資源的文件格式,它...
    好怕怕閱讀 7,874評(píng)論 1 8
  • 翻譯:莫銘原文地址:AssetBundle usage patterns 本系列中的上一篇文章覆蓋了AssetBu...
    莫銘閱讀 5,695評(píng)論 1 12
  • 工具Unity 中的資源來(lái)源有三個(gè)途徑:一個(gè)是Unity自動(dòng)打包資源,一個(gè)是Resources,一個(gè)是AssetB...
    某人在閱讀 9,193評(píng)論 0 5
  • 關(guān)于清水泥有兩種說(shuō)法: 第一種:清水泥是一種煉泥方法,以不加其他雜料直接粉碎成泥方法煉制的泥料統(tǒng)稱清水泥。清水泥以...
    石破天聊紫砂閱讀 1,275評(píng)論 0 1
  • 感謝關(guān)注我并且挺我的所有的朋友圈家人們。這幾天過(guò)得很充實(shí),雖然之前每天也都是在忙,但是現(xiàn)在才發(fā)現(xiàn)因?yàn)闆](méi)有計(jì)劃所以自...
    河延小姐姐閱讀 161評(píng)論 0 0

友情鏈接更多精彩內(nèi)容