AssetBundle實戰(zhàn):資源冗余袍暴,分包策略些侍,加載和卸載

一.前文提要

AssetBundle是用于包裝和加載資源的一個重要工具。我們可以在運行時對游戲內(nèi)容進(jìn)行更新政模。這允許開發(fā)者提交更小的應(yīng)用程序岗宣,然后通過網(wǎng)絡(luò)將數(shù)據(jù)進(jìn)行傳輸桥言,可以減輕運行時的壓力罩引,可以有選擇的加載和卸載內(nèi)容來進(jìn)行優(yōu)化。

不同于Resources加載非常直接的使用方式五芝,AssetBundle的使用方式會更加繁瑣和復(fù)雜趁猴,需要自己設(shè)計打包策略刊咳,做包引用計數(shù),管理加載和卸載等儡司。

我們?nèi)绻谟螒蛑惺褂胊ssetbundle娱挨,需要進(jìn)行以下幾個步驟:

  1. 根據(jù)分包策略規(guī)劃每個包內(nèi)的資源;

  2. 構(gòu)建所有包資源枫慷;

  3. 如果是ab資源放在遠(yuǎn)端让蕾,則在游戲運行時下載ab包;

  4. 加載ab包或听;

  5. 在合適的時機卸載不再使用的ab包探孝;


AssetBundle的資源冗余

資源重復(fù)入包,也稱資源冗余誉裆,指的是同一個資源被打包入多個不同的ab包內(nèi)顿颅。

資源冗余導(dǎo)致包體過大,占用內(nèi)存和帶寬足丢。

這個概念在下文中會多次提到粱腻,也是工作中常遇到的一個非常重要的問題。

為什么會資源重復(fù)入包斩跌?

這與unity構(gòu)建ab包的邏輯有關(guān)绍些。構(gòu)建ab包時,會自動將ab包內(nèi)的資源和這些資源依賴的所有資源打包耀鸦。

例如下圖所示:

資源重復(fù)入包范例
  • 預(yù)制體A依賴于C 柬批,E, 預(yù)制體B依賴于D 袖订,E氮帐;

  • 預(yù)制體A放入ab包 A 中,預(yù)制體B放入ab包 B 中洛姑。

則在打包后上沐,ab包A中會包含A C E3個資源,ab包B中會包含B D E3個資源楞艾。

這時預(yù)制體 A 和 B 都依賴的圖片 E 被打包了2次参咙,這時就產(chǎn)生了資源重復(fù)入包龄广。

那我們該如何避免資源重復(fù)入包呢?下文的分包策略就是為了處理這個問題蕴侧。


二. 分包策略

分包策略指的是按照一定的規(guī)則蜀细,將需要入包的所有資源,按照類型/大小/模塊等因素分配到不同的assetbundle包中戈盈。

好的分包策略奠衔,可以避免資源重復(fù)入包,減少加載ab時的時間塘娶,減少內(nèi)存占用和流量消耗归斤。

1. 為什么要分包?

在設(shè)計分包策略前刁岸,我們需要先了解分包的原因脏里,即ab資源的分包主要為了解決什么問題?

先舉例2個極端的分包情況虹曙,我們可以看下各自的缺點迫横。

第一種:所有資源都放入一個assetbundle包中。

這種情況下只會有一個ab包酝碳,這個ab包內(nèi)包含了所有的資源矾踱。會有以下缺點:

  1. 加載任意資源都會導(dǎo)致整個ab包加載入內(nèi)存,導(dǎo)致加載時間過長疏哗,內(nèi)存占用過大呛讲;

  2. 如果有資源熱更新,意味著每個資源的修改都將會重新下載整個ab包返奉,浪費帶寬贝搁;

第二種:每個獨立的資源都單獨打一個assetbundle包。

這種情況下有多少個資源芽偏,則會有多少個ab包雷逆。會有以下缺點:

  1. 因為每個ab包結(jié)構(gòu)上分為包頭和資源數(shù)據(jù),更多的ab包意味著有更多的包頭數(shù)據(jù)污尉,占用更多的包體和內(nèi)存(如下圖)膀哲;
同樣數(shù)據(jù)大小下不同ab包的影響
  1. ab包本地加載時,文件尋址的時間會遠(yuǎn)大于文件讀取的時間十厢。這意味著在數(shù)據(jù)大小相同時等太,更多的文件個數(shù)讀取時間會更長捂齐。例如1000個1M的文件的讀寫時間會遠(yuǎn)遠(yuǎn)大于1個1G的文件的讀寫時間蛮放;

  2. ab包從服務(wù)器下載時,更多的ab包意味著更多的http請求數(shù)奠宜。會有3方面的影響包颁。

    1. 因為http有請求頭的緣故瞻想,同等大小的數(shù)據(jù)傳輸時,更多的http請求數(shù)意味著更多的帶寬占用娩嚼;

    2. http請求中需要有建立鏈接的時間蘑险,更多的http請求意味著更多的時間花在建立鏈接上;

    3. 更多的http請求會對服務(wù)器并發(fā)數(shù)和帶寬占用產(chǎn)生影響岳悟;

根據(jù)上面2種極端情況佃迄,我們對于assetbundle分包的最優(yōu)解有了結(jié)論:在ab包數(shù)量更少的情況下,盡量滿足每個ab包內(nèi)的資源不重復(fù)贵少,各個ab包的使用場景不相交呵俏。


2. 分包的基本原則

Unity官方推薦的ab包分配方式有以下幾種:

按邏輯進(jìn)行分類

即按該資源被哪個功能應(yīng)用到,同種功能用到的資源打到一個AB包內(nèi)

  • 將一個UI界面的所有圖片紋理滔灶,布局文件打包到一個AB包

  • 將一個角色的所有動畫普碎,模型打包到一個AB包

  • 將一些公用的資源打包到一個AB包

按類型分類

  • 將同一個類型下的資源打包到一個AB包中

  • 如將Windows和Mac平臺下使用到的不同Shader資源分類打包

  • 將不同版本的Unity AB包進(jìn)行分類打包

同時使用的打包

即考慮到哪些AB包可能會在某個時間段一起使用,則打包到同一個AB包中

  • 如某關(guān)卡下需要加載的所有資源一起打包

  • 某個場景下需要加載的所有資源录平,你應(yīng)該盡可能將所有AB包依賴項都打包進(jìn)來麻车,避免加載其他依賴項

在實際的工作中,按照單一的分配原則有比較大的局限性斗这,往往不能達(dá)到最優(yōu)解动猬。

混合搭配才是王道

以下是官方給出的一些分類建議:

  • 將經(jīng)常更新和很少更改的資源分開打包表箭;

  • 將基本會同時使用的資源打包枣察,如模型和它用到的紋理,動畫一起打包燃逻;

  • 將一些很多資源會引用到的公共資源分開打包序目,避免重復(fù)打包;

  • 如果兩組幾乎不可能同時加載的資源分開打伯襟,如Standard和High解析度資源分開打猿涨;

  • 如果一次加載某個AB包經(jīng)常用到少于50%其中的資源,則應(yīng)該分開打包姆怪;

  • 考慮合并比較小但經(jīng)常一起使用的AB包叛赚;

  • 如果某組資源只是同個資源的不同版本分類,使用variant打包(如不同語言版本的同個資源)稽揭;


3. 手動分包模式

手動分包模式:通過手動配置資源的ab標(biāo)簽管理AB資源分包

手動配置ab包的標(biāo)簽

我們可以手動指定每個資源的ab分包標(biāo)簽俺附,當(dāng)分配好后,調(diào)用BuildPipeline.BuildAssetBundles(xxx) 接口即可生成ab包資源溪掀。

如果使用這種方式事镣,每次僅僅操作一個資源或文件夾,無法對整個項目中的ab資源分包有全面的了解揪胃。

所以一般都會搭配可視化工具來使用璃哟,使用可視化的ab資源引用窗口工具氛琢,從而詳細(xì)了解項目中的ab資源分配狀況,更好縷清資源引用關(guān)系随闪。

官方的可視化工具有:Unity Asset Bundle Browser阳似。其他各種框架大都有內(nèi)置的類似工具,不一一列舉铐伴。

此外如果不使用第三方工具撮奏,這種方式無法直接查看資源重復(fù)入包。即一份資源在ABC3個ab包中使用当宴,則會重復(fù)構(gòu)建3份挽荡,導(dǎo)致資源冗余。

當(dāng)然我們遍歷一遍所有資源即供,是可以找出所有冗余的資源定拟。有很多工具也有對應(yīng)的功能,例如上文提到的AssetBundle Brower逗嫡。


4. 自動分包模式

手動分包模式下青自,需要花費較大的精力來合理規(guī)范ab包,從而減少資源冗余驱证。通過自動模式處理ab包分包則節(jié)省了不少精力延窜。

自動模式不需要手動指定每個資源/文件夾的ab分包標(biāo)簽,而是通過一套自定義的規(guī)則抹锄,將項目中使用到的資源劃分為不同的ab包逆瑞。

這套規(guī)則必須保證:不產(chǎn)生冗余資源,各ab包大小合理伙单,最好符合同一個ab包內(nèi)的資源在邏輯/類型/使用場景下有一致性的原則获高。

一種分包策略如下:

指定一個目錄,目錄下的所有資源可以動態(tài)加載吻育。根據(jù)資源的引用關(guān)系念秧,將所有資源劃分到不同的ab包中。規(guī)則如下:

  1. 如果資源A被引用次數(shù)為0布疼,則資源A單獨劃分為一個ab包摊趾;

  2. 如果資源A被引用次數(shù)為1,僅被資源B引用游两,則資源A被劃分到B所屬的ab包中砾层;

  3. 如果資源A被引用次數(shù)>=2,被資源B1Bn引用時贱案,如果資源B1Bn在不同ab包中肛炮,則A單獨劃分為一個ab包;如果資源B1~Bn在同一ab包中,則A也被劃分到所屬的同一ab包中铸董。

這種分包策略下的包劃分如下圖:

自動分包下的范例


5. 特殊資源的分包策略

場景資源

場景assetbundle和其他資源assetbundle需要區(qū)分,場景以及其使用的資源要單獨劃分為一個ab包肴沫。

因為兩者在格式和內(nèi)容上略有不同粟害,unity針對場景assetbundle的串流加載做了優(yōu)化。

shader資源

常見的問題:打包ab后在手機上shader丟失颤芬。主要原因與shader的分包策略和shader變體機制有關(guān)悲幅。

具體原因可以查看我的另一篇文章:AssetBundle中的shader變體丟失問題,這里只說下打包shader的最佳方案:

  • 把assetbundle資源中引用到的shader都放到一個ab包中站蝠,在進(jìn)入游戲時首先加載此ab包汰具,這樣可以保證后續(xù)所有使用的材質(zhì)沒有問題。
  • 常用到且變體數(shù)量少的shader菱魔,可以將shader加入到Always Included Shaders 中留荔,然后在打包ab資源時剔除這些shader。
  • 需要assetbundle打包的shader澜倦,使用ShaderVirantCollection定義需要打包的變體聚蝶。可以通過shader control插件來搜集材質(zhì)球使用到的shader變體藻治,結(jié)合人工查找代碼中調(diào)用使用到的變體碘勉。

圖集資源

常見問題:圖集內(nèi)貼圖資源重復(fù)入包。主要原因與貼圖和圖集的打包策略有關(guān)桩卵,也與圖集是否勾選Include In Build有關(guān)验靡。

具體原因不細(xì)說,只說打包圖集資源的最佳方案:

  1. 勾選include in build雏节,同一個圖集內(nèi)的所有圖元放在同一個AssetBundle中胜嗓,但是圖集不入ab包;

  2. 不勾選include in build钩乍,同一個圖集內(nèi)的所有圖元放在同一個AssetBundle中兼蕊,圖集入ab包,需要在代碼中添加圖集動態(tài)綁定回調(diào)件蚕;


三. 構(gòu)建AssetBunlde


1. 構(gòu)建AB包的接口方法

有2種常用的ab資源構(gòu)建的接口:

 // 方法1
 BuildPipeline.BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)
 // 方法2 相比1需要傳入AssetBundleBuild[]
 BuildPipeline.BuildAssetBundles(string outputPath, AssetBundleBuild[] builds, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)
  1. 不傳ab包分包列表 按照資源在Inspector最下面的分包標(biāo)識構(gòu)建ab包(如下圖)孙技。

  2. 傳入ab包分包列表,按照分包列表構(gòu)建對應(yīng)的ab包排作;

這種方式可以不通過方法1中的編輯分包標(biāo)識來設(shè)置ab包牵啦,而是可以自定義分包規(guī)則。


2. 構(gòu)建AB包的構(gòu)建參數(shù)

所有參數(shù)定義在BuildAssetBundleOptions枚舉下妄痪。

None :不使用任何特殊選項構(gòu)建 assetBundle哈雏。
UncompressedAssetBundle :Don't compress the data when creating the AssetBundle.
DisableWriteTypeTree :不包括 AssetBundle 中的類型信息。
DeterministicAssetBundle :使用存儲在資源包中對象的 ID 的哈希構(gòu)建資源包。
ForceRebuildAssetBundle :強制重新構(gòu)建 assetBundle裳瘪。
IgnoreTypeTreeChanges :在執(zhí)行增量構(gòu)建檢查時忽略類型樹更改土浸。
AppendHashToAssetBundleName :向 assetBundle 名稱附加哈希。
ChunkBasedCompression :創(chuàng)建 AssetBundle 時使用基于語塊的 LZ4 壓縮彭羹。
StrictMode :如果在此期間報告任何錯誤黄伊,則構(gòu)建無法成功。
DryRunBuild :進(jìn)行干運行構(gòu)建派殷。
DisableLoadAssetByFileName :禁用按照文件名稱查找資源包 LoadAsset还最。
DisableLoadAssetByFileNameWithExtension :禁用按照帶擴展名的文件名稱查找資源包 LoadAsset。
AssetBundleStripUnityVersion :在構(gòu)建過程中刪除存檔文件和序列化文件頭中的 Unity 版本號毡惜。

下面是一些常用的參數(shù)的詳解:
DisableWriteTypeTree: 打包AB資源時會默認(rèn)寫入TypeTree的信息拓轻,這樣可以保證AssetBundle文件的向下兼容性,即高版本可以支持以前低版本制作的AssetBundle文件经伙。

如果開啟DisableWriteTypeTree選項扶叉,則可能造成AssetBundle對Unity版本的兼容問題,但關(guān)閉TypeTree會使Bundle更小帕膜。

IgnoreTypeTreeChanges:在執(zhí)行增量構(gòu)建檢查時忽略類型樹更改辜梳。

此選項允許您在執(zhí)行增量構(gòu)建檢查時忽略類型樹更改。設(shè)置此標(biāo)志后泳叠,如果包含的資源沒有更改作瞄,但類型樹發(fā)生了更改,則系統(tǒng)不會重新構(gòu)建目標(biāo) assetBundle危纫。

DisableLoadAssetByFileName:禁用按照文件名稱查找資源包 LoadAsset宗挥。

默認(rèn)情況下,可通過三種方式查找資源包中的相同資源:完整資源路徑种蝶、資源文件名稱和帶擴展名的資源文件名稱契耿。完整路徑在資源包中進(jìn)行了序列化,而文件名稱以及帶擴展名的文件名稱是在從文件中加載資源包時生成的螃征。

示例:“Assets/Prefabs/Player.prefab”搪桂、“Player”和“Player.prefab”

此選項將在資源包上設(shè)置一個標(biāo)志,以防止創(chuàng)建資源文件名稱查找盯滚。此選項會節(jié)省資源包的運行時內(nèi)存和加載性能踢械。


3. 打包生成的文件

打包生成的文件

在一次打包后會生成很多文件,根據(jù)用途分為以上3種:

  1. 本次構(gòu)建的所有ab資源的清單列表魄藕,通過AssetBundleManifest加載使用内列。可以獲取所有的ab包列表背率,ab包的依賴列表等话瞧。

  2. 單個ab資源源文件嫩与,通過AssetBundle.LoadFromXXX() 加載使用。

  3. 單個ab資源的manifest文件交排,包含ab資源的信息划滋,如CRC碼,hash值埃篓,包內(nèi)的資源列表处坪,依賴包等。如下圖所示:


    manifest文件


四. 加載AssetBundle

1. AssetBundleManifest的接口

manifaset文件主要用于記錄 AssetBundle 里面的文件信息都许,AB包之間的依賴關(guān)系稻薇,文件夾下所有AB的信息嫂冻,官方有提供對應(yīng)的類AssetBundleManifest胶征。關(guān)鍵API:

var bundleManifest = assetBundle.LoadAsset<AssetBundleManifest>(string name);
 //獲取目標(biāo)ab的所有依賴(遞歸查找依賴的依賴)
bundleManifest.GetAllDependencies(string abName);

 //獲取文件夾下所有ab信息
bundleManifest.GetAllAssetBundles();

 //獲取目標(biāo)ab的直系依賴(不遞歸查找依賴的依賴
bundleManifest.GetDirectDependencies(string abName);


2. 加載ab資源的接口

// 從文件中加載
AssetBundle.LoadFromFile();
AssetBundle.LoadFromFileAsync();
// 從內(nèi)存中加載
AssetBundle.LoadFromMemory();
// 從網(wǎng)絡(luò)下載
UnityWebRequestAssetBundle.GetAssetBundle();

① AssetBundle.LoadFromFile(Async)

最常用也是最推薦使用的方法。

這個方法可以高性能的加載沒有壓縮或者通過LZ4方法壓縮的AssetBundle桨仿。

使用這個方法的時候睛低,大部分平臺只加載AssetBundle的包頭,剩下的數(shù)據(jù)仍然在硬盤上服傍。AssetBundles的對象會按需要進(jìn)行加載钱雷,或者被間接引用到的時候加載。在這個情境下不會有額外的內(nèi)存被消耗吹零。

② AssetBundle.LoadFromMemory(Async)

不建議使用的API罩抗。常用于通過加密過的ab資源的加載。

如果你通過下載或者其他方法已經(jīng)把Assetbundle的字節(jié)保存到了內(nèi)存中的一個數(shù)組中灿椅,就能通過此函數(shù)進(jìn)行加載套蒂。

使用這個方法的時候,底層會把內(nèi)存中已經(jīng)加載好的assetbundle數(shù)組byte[]拷貝到一個新分配的茫蛹、相鄰的地址上操刀,如果使用了LZMA壓縮方法,拷貝的時候還會順便解壓婴洼。造成的問題是內(nèi)存使用的峰值至少是assetbundle的兩倍骨坑。

③ UnityWebRequestAssetBundle.GetAssetBundle()

從遠(yuǎn)端服務(wù)器加載ab資源時推薦的方法。

UnityWebRequest類允許開發(fā)者定義unity應(yīng)該怎么處理下載的數(shù)據(jù)柬采,避免不必要的內(nèi)存消耗欢唾。

使用DownloadHandlerAssetBundle 類可以對下載進(jìn)行配置,使用一個worker線程流式下載數(shù)據(jù)粉捻,并存放在一個可變大小的buffer匈辱,或者某個臨時的存儲空間中。DownloadHandler 不會復(fù)制已下載的bytes杀迹。

對于LZMA壓縮的Assetbundles亡脸,下載的時候會順便解壓押搪,存放的時候通過LZ4再次壓縮,可以通過Caching.CompressionEnabled 設(shè)置浅碾。

下載完成后大州,可以通過DownloadHandler的屬性對assetbundle進(jìn)行訪問,這個行為類似于AssetBundle.LoadFromFile垂谢。

 UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(assetBundlePath, 0);
 var opt = request.SendWebRequest();
 opt.completed += (_) =>
 {
     AssetBundle = DownloadHandlerAssetBundle.GetContent(request);
 };

④ WWW.LoadFromCacheOrDownload

舊版API厦画,因為性能問題已被廢棄,建議使用UnityWebRequest滥朱。


五. 卸載AssetBundle

為什么要卸載AssetBundle根暑?

每次加載AB包都會有內(nèi)存的占用,如果一直不卸載徙邻,隨著游戲的運行不停加載使用到的新AB包排嫌,內(nèi)存占用會越來越大。

哪些AssetBundle可以卸載缰犁?

當(dāng)前運行時沒有使用到的Assetbundle可以卸載淳地。沒有使用到的Assetbundle指的是內(nèi)部的資源當(dāng)前未被引用。

想要卸載AssetBundle帅容,首先需要了解它在內(nèi)存中的占用組成颇象。


AssetBundle的內(nèi)存占用

下面內(nèi)容引用自 AssetBundle內(nèi)存 - csdn

AssetBundle的內(nèi)存占用

接下來詳細(xì)看看每部分的含義。

黑色部分:www類本身占用內(nèi)存并徘,通過www接口加載AssetBundle才會有這部分內(nèi)存遣钳,www對象保留了一份對WebStream數(shù)據(jù)(粉色部分)的引用。使用www =null 或者 www.dispose()釋放麦乞。

其中www.dispose()會立即釋放蕴茴,而www = null會等待垃圾回收。釋放www后WebStream的引用計數(shù)會相應(yīng)減一路幸。

橙色部分:官方稱為WebStream數(shù)據(jù)荐开,是數(shù)據(jù)真正的存儲區(qū)域。當(dāng)AssetBundle被加載進(jìn)來后简肴,這部分內(nèi)存就被分配了晃听。

它包含3個內(nèi)容:壓縮后的AssetBundle本身、解壓后的資源以及一個解壓緩沖區(qū)(圖綠)砰识。無論www(黑色部分)還是后面會提到的AssetBundle對象(粉色部分)能扒,都只是有一個結(jié)構(gòu)指向了WebStream數(shù)據(jù),從而能對外部提供操作真正資源數(shù)據(jù)的方法辫狼。而當(dāng)www對象和AssetBundle對象釋放時初斑,WebStream數(shù)據(jù)的引用計數(shù)也會相應(yīng)減1。當(dāng)WebStream數(shù)據(jù)引用計數(shù)為0時膨处,系統(tǒng)會自動釋放见秤。

但為了不頻繁地開辟和銷毀解壓Buffer砂竖,其中綠色Decompression解壓緩沖區(qū)Unity會至少保留一份。例如同時加載3個AssetBundle時鹃答,系統(tǒng)會生成3個Decompression Buffer乎澄,當(dāng)解壓完成后,系統(tǒng)會銷毀兩個测摔。

粉色部分:AssetBundle對象置济,引用了橙色WebStream數(shù)據(jù)部分,并提供了從WebStream數(shù)據(jù)中加載資源的接口锋八。通過AssetBundle.Unload(bool unloadAllLoadedObjects)釋放浙于。

如果調(diào)用AssetBundle.Unload(false),將釋放AssetBundle對象本身挟纱,其對WebStream引用也將減少羞酗,從而可能引起WebStream釋放,我們也就無法再通過接口或依賴關(guān)系從該AssetBundle加載資源樊销。但已加載的資源還可以正常使用整慎。

如果調(diào)用的是AssetBundle.Unload(true)脏款,不僅會釋放WebStream部分围苫,所有被加載出來的資源將被釋放。

無論true或false撤师,AssetBundle.Unload()都將銷毀AssetBundle剂府,銷毀后調(diào)用該AssetBundle對象的任何方法都不會生效或產(chǎn)生報錯,也就是說這個接口只能被調(diào)用一次剃盾,不能先調(diào)用unload(false)再調(diào)用unload(true)腺占。


卸載的接口

AssetBundle.Unload(false)

會把 Bundle 卸載,但是已經(jīng)從 Bundle 里加載出來的 資源 是不會被卸載的痒谴。

AssetBundle.Unload(true)

不但會卸載 Bundle衰伯,也會卸載已經(jīng)從 Bundle 里加載出來的 所有資源,哪怕這些 資源 還被引用著积蔚。


常用的卸載策略

需要通過引用計數(shù)管理ab包意鲸。

推薦的卸載方式:

  1. 加載ab包中資源時,引用計數(shù)+1尽爆,釋放已加載的資源時怎顾,引用計數(shù)-1;

  2. 當(dāng)引用計數(shù)為0時漱贱,調(diào)用AssetBundle.Unload(true) 徹底卸載ab包資源和從ab包中加載出來的資源槐雾;


六. 其他細(xì)節(jié)

壓縮方式

Unity3D引擎為我們提供了三種壓縮策略來處理AssetBundle的壓縮,即:

  • LZMA格式:默認(rèn)下采用幅狮,壓縮為序列化流文件募强,高壓縮比株灸,解壓縮時間長;
  • LZ4格式:基于chunk壓縮擎值,中壓縮比蚂且,解壓快;
  • 不壓縮
    可以自行壓縮ab包幅恋,然后第一次進(jìn)入游戲時進(jìn)行解壓杏死,從而減少包體和體驗的流暢。


CRC校驗

AssetBundle.LoadFromFile(string path, uint crc, ulong offset);

AB包從服務(wù)端下載到本地捆交,中途因為某些原因?qū)е聜鬏數(shù)奈募粨p壞了淑翼,但損壞的文件,不能使用品追。因此玄括,需要對文件進(jìn)行完整性的校驗。
目前比較流行的算法有CRC肉瓦、MD5遭京、SHA1。它們都是通過對數(shù)據(jù)進(jìn)行計算泞莉,來生成一個校驗值哪雕,我們可以根據(jù)該值來檢查數(shù)據(jù)的完整性。它們的不同點有以下幾點:
(1)算法不同:CRC采用多項式除法鲫趁、MD5和SHA1使用的是替換斯嚎、輪轉(zhuǎn)等方法。
(2)安全性不同:這里的安全性是指檢錯的能力挨厚,即數(shù)據(jù)的錯誤能通過校驗位檢測出來堡僻。CRC的安全性跟多項式有很大關(guān)系,相對于MD5和SHA1要弱很多疫剃;MD5的安全性很高钉疫;SHA1的安全性最高。
(3)效率不同:CRC的計算效率很高巢价;MD5和SHA1比較慢牲阁。
(4)用途不同:CRC一般用作通信數(shù)據(jù)的校驗;MD5和SHA1用于安全(Security)領(lǐng)域蹄溉,比如文件校驗咨油、數(shù)字簽名。


加密方式

  1. 位運算:打出ab包后柒爵,二進(jìn)制讀取然后對每位與密鑰進(jìn)行異或操作役电。A異或Key=B, B異或Key=A.因此讀取的時候需要通過AssetBundle.LoadFromMemory進(jìn)行加載,所以需要雙份內(nèi)存占用棉胀。

  2. offset加密:打包時加上一定長度的字段作為offset法瑟,讀取時通過官方的api進(jìn)行讀燃较ァ:

AssetBundle abBundle = AssetBundle.LoadFromFile(assetBundleMapPath,0,8);
  1. unity中國區(qū)特供版有加密方法,打包前先設(shè)置秘鑰:
(AssetBundle.SetAssetBundleDecryptKey("888888fff")霎挟;


開源庫推薦

xasset:https://github.com/xasset/xasset
ABSystem:https://github.com/tangzx/ABSystem
FSFramework:https://github.com/mr-kelly/KSFramework
BundleMaster:https://github.com/mister91jiao/BundleMaster


參考鏈接:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窝剖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子酥夭,更是在濱河造成了極大的恐慌赐纱,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熬北,死亡現(xiàn)場離奇詭異疙描,居然都是意外死亡,警方通過查閱死者的電腦和手機讶隐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門起胰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巫延,你說我怎么就攤上這事效五。” “怎么了炉峰?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵畏妖,是天一觀的道長。 經(jīng)常有香客問我讲冠,道長瓜客,這世上最難降的妖魔是什么适瓦? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任竿开,我火速辦了婚禮,結(jié)果婚禮上玻熙,老公的妹妹穿的比我還像新娘否彩。我一直安慰自己,他們只是感情好嗦随,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布列荔。 她就那樣靜靜地躺著,像睡著了一般枚尼。 火紅的嫁衣襯著肌膚如雪贴浙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天署恍,我揣著相機與錄音崎溃,去河邊找鬼。 笑死盯质,一個胖子當(dāng)著我的面吹牛袁串,可吹牛的內(nèi)容都是我干的概而。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼囱修,長吁一口氣:“原來是場噩夢啊……” “哼赎瑰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起破镰,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤餐曼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鲜漩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晋辆,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年宇整,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓶佳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡鳞青,死狀恐怖霸饲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情臂拓,我是刑警寧澤厚脉,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站胶惰,受9級特大地震影響傻工,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜孵滞,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一中捆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坊饶,春花似錦泄伪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至痘绎,卻和暖如春津函,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背孤页。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工尔苦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓蕉堰,卻偏偏與公主長得像凌净,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子屋讶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容