1. 程式人生 > >AssetBundle 資源打包 載入 解除安裝

AssetBundle 資源打包 載入 解除安裝

1 給要打包的資源設定標記,表示對應的包名:

  

2 Unity5 AssetBundle不需要我們來管理引用關係了

3 可以使用程式碼批量設定包名

 AssetImporter ai = AssetImporter.GetAtPath(assetPath);
 i.assetBundleName = xxx;
 ai.assetBundleVariant = xxx;

4 Build the AssetBundles

Create a folder called Editor in the Assets folders, and place a script with the following contents in the folder:

using UnityEditor;

public class CreateAssetBundles
{
    [MenuItem("Assets/Build AssetBundles")]//選單選項
    static void BuildAllAssetBundles()
    {
        string assetBundleDirectory = "Assets/AssetBundles";//打包到哪裡
        if(!Directory.Exists(assetBundleDirectory))
{
    Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
    }
}

BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);

是主要的打包函式。

其中第二個引數,

BuildAssetBundleOptions

BuildAssetBundleOptions.None:使用LZMA演算法壓縮,壓縮的包更小,但是載入時間更長。使用之前需要整體解壓。一旦被解壓,這個包會使用LZ4重新壓縮。使用資源的時候不需要整體解壓。在下載的時候可以使用LZMA演算法,一旦它被下載了之後,它會使用

LZ4演算法儲存到本地上。

BuildAssetBundleOptions.UncompressedAssetBundle:不壓縮,包大,載入快

BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4壓縮,壓縮率沒有LZMA高,但是我們可以載入指定資源而不用解壓全部。

注意使用LZ4壓縮,可以獲得可以跟不壓縮想媲美的載入速度,而且比不壓縮檔案要小。

https://docs.unity3d.com/Manual/AssetBundles-Building.html

呼叫該函式,unity會自動根據資源的標籤進行打包,而且是增量打包,

  a.對於資源沒有變更的bundle包,不會觸發重新打包;
  b.資源沒變,即使生成目錄下的bundle包被刪除了,unity也不會重新打包;
  c.生成目錄下的bundle包對應的manifase被刪了,會重新打包;
  d.可以使用BuildAssetBundleOptions.ForceRebuildAssetBundle引數觸發強制重新打包。
 

5  生成的bundle包資源目錄:

  

  StreamingAssets:一個AssetBundle包,內含AssetBundleManifest型別的Asset,記錄了所有bundle包及相互間的依賴關係。
    執行時需要首先載入這個AssetBundleManifest,然後根據其提供的depence資訊載入依賴的bundle包。
  StreamingAssets.manifest:全域性manifest,全域性manifest的名字和打包生成的目錄同名,不是固定的,這裡是生成在StreamingAssets目錄下。
  Cube.assetbundle:資源bundle。

  Cube.assetbundle.manifest:每個資源自己的manifest,與bundle一一對應,只是用來做增量build,執行時根本不需要。

^_^場景打包成AssetBundle資源和普通資源打包有所區別。

這是一個普通的assetbundle

The Scene AssetBundle is different to normal AssetBundles, in that it is optimized for stream loading of a Scene and its content.

Scene AssetBundle略有不同,為

載入場景Scene AssetBundle用到的介面:

SceneManager.LoadScene()或者SceneManager.LoadSceneAsync()

第二個引數決定了是否銷燬之前載入的GameObject

    manifest檔案裡面定義了使用的資源和依賴:

載入Manifests檔案可以處理資源的依賴

AssetBundleassetBundle = AssetBundle.LoadFromFile(manifestFilePath);

AssetBundleManifest manifest =

assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

string[]dependencies = manifest.GetAllDependencies("assetBundle"); //Pass the name of the bundleyou want the dependencies for.

foreach(string dependency in dependencies)

{

AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));

6壓縮格式
  (1)LZMA:預設壓縮格式,壓縮比大,省空間,使用前需要解壓整個壓縮包;
  (2)LZ4:5.3版本新增, 40%–60% 的壓縮率,開啟BuildAssetBundleOptions.ChunkBasedCompression打包引數即可。
    LZ4演算法是“基於塊”的,因此當物件從一個LZ4壓縮包載入時,僅用於該物件的相應塊會被解壓,不需要解壓整個包。

    所以LZ4和不壓縮資源一樣,都可以不解壓,而直接讀取包中的資源的。

AssetBundle載入方式對比

  主要的載入方式有以下四種,前兩種還兼具下載的功能,後兩種都有對應的非同步介面:

        使用哪一種方法取決於bundle的提供形式:

  (1)WWW.LoadFromCacheOrDownload:走本地cache,沒有就下載並解壓(然後再LZ4壓縮),有就用;
    如果沒有快取,對於未壓縮的和LZ4壓縮的AssetBundle包,unity會直接把它們拷貝到快取目錄裡面,對於LZMA壓縮的,會先解壓然後重新壓縮成LZ4格式,然後快取它。可以通過Caching.compressionEnabled控制是否壓縮快取。
  (2)LoadFromFile:最快的方式,區別於4.x版本,可以直接使用壓縮資源;
    如果是UnCompress或LZ4,直接從disk讀取

    如果是LZMA,會先解壓到memory,然後讀取

For users intending to load from local storage, you’ll be interested in the AssetBundles.LoadFromFile API. Which looks like this:

public class LoadFromFileExample extends MonoBehaviour {
    function Start() {
        var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
        if (myLoadedAssetBundle == null) {
            Debug.Log("Failed to load AssetBundle!");
            return;
        }
        var prefab = myLoadedAssetBundle.LoadAsset.<GameObject>("MyObject");
        Instantiate(prefab);
    }
}

  (3)LoadFromMemoryAsync:從記憶體載入,一般用於加密資源。

//非同步載入資源
        AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path1));
        yield 
return request;
        
//載入共同依賴資源,如貼圖、材質
        AssetBundleCreateRequest request2 = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path2));
        yield 
return request2;
        AssetBundle ab = request.assetBundle;
        AssetBundle ab2 = request2.assetBundle;

        
//使用裡面的資源
        GameObject wallPrefab1 = ab.LoadAsset("CubeWall");

        Instantiate(wallPrefab1);

        (4)UnityWebRequest

    首先是建立一個web request(呼叫UnityWebRequest.GetAssetBundle), 然後進行資源的獲取(呼叫DownloadHandlerAssetBundle.GetContent)

StartCoroutine(InstantiateObject());

IEnumerator InstantiateObject()

    {
        string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;         UnityEngine.Networking.UnityWebRequest request =             UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
        yield return request.Send();
        AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
        GameObject cube = bundle.LoadAsset<GameObject>("Cube");
        GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");
        Instantiate(cube);
        Instantiate(sprite);
    }


  使用方式建議:
  (1)隨包資源StreamingAssets:
    未壓縮或LZ4壓縮:LoadFromFile;
    LZMA壓縮:可使用 WWW.LoadFromCacheOrDownload解壓縮到本地磁碟。
  (2)熱更新資源:LZMA+WWW.LoadFromCacheOrDownload+Caching.compressionEnabled;
  (3)加密資源:LZ4+LoadFromMemory;

  (4)自己壓縮的資源:UncompressAssetBundle的AssetBundle包+自己的演算法壓縮+LoadFromFileAsync。

WWW.LoadFromCacheOrDownload會被UnityWebRequest取代

資源解除安裝
  AssetBundle.Unload(false):幹掉壓縮包,bundle不再可用,即不能再通過bundle.Load載入資源;
  AssetBundle.Unload(true):幹掉壓縮包,和所有從中載入(load)出來的資源。
  所以解除安裝資源一般有兩種玩法:
  (1)AssetBundle.Unload(false)結合Resource.UnloadUnusedAssets()
  (2)碎片化使用AssetBundle.Unload(true)

  具體怎麼用要結合遊戲本身的資料特點來定製。關於要不要Unload釋放AssetBundle本身的記憶體,也有兩種主流玩法,一種是即用即卸(LoadAsset以後立馬釋放AssetBundle),一種是快取AssetBundle不解除安裝,兩種方法各有優劣,需結合使用。

unity在場景中的Object被移除的時候不自動釋放objects,資源的清理需要再特定的時間觸發(場景切換)或者手動的管理。所以怎麼載入和解除安裝資源顯得尤為重要,不合適的載入可能會導致資源的重複載入,不合適的解除安裝可能會帶來資源的缺失(比如丟失貼圖)。

  對於assetbundle的資源管理,最重要的是掌握什麼時候呼叫AssetBundle.Unload(bool)這個函式,傳入true/false會有不同的解除安裝策略。這個API會解除安裝對應的assetbundle的頭部資訊,引數對應著是否同時解除安裝從該assetbundle中例項化的所有Objects。

  AssetBundle.Unload(true)會解除安裝assetbundle中的所有gameobjects以及其依賴關係,但是並不包括基於其Objects例項化(複製)的Object(因為這些object不屬於該assetbundle,只是引用),所以當解除安裝貼圖相關的assetbundle的時候,場景中對其引用的例項化物體上會出現貼圖丟失,也就是場景中會出現紅色的區域,unity都會將其處理成貼圖丟失。

  舉例說明,假設材質M來自於assetbundle AB, 如果 AB.Unload(true), 那麼場景中任何M的例項都會被解除安裝和銷燬,如果AB.Unload(false), 那麼就會切斷材質M例項與AB之間的關係:

  那麼如果該assetbundle AB在後面再次被載入,unity不會重新關聯其關係,這樣在後續的使用中,就會出現一份材質的多個例項:

  所以通常情況下,AssetBundle.Unload(false) 並不能帶來較為合理的釋放結果,AssetBundle.Unload(true)通常用來確保不會在記憶體中多次拷貝同一個資源,所以其更多的被專案所採納,此外還有兩個常用的方法用來確保其使用:

1)在遊戲中,對於場景的解除安裝有明確的規劃,比如在場景切換中或者場景載入中;

2)管理好對每個單獨的object的計數,只有在沒有引用的時候才解除安裝該assetbundle,這樣可以規避載入和解除安裝過程中的多份記憶體拷貝問題。

  如果要使用AssetBundle.Unload(false), 那麼這些例項化的物件可以通過2中途徑解除安裝:

1)清除對不需要物體的所有引用,場景和程式碼中都需要清楚,然後呼叫Resources.UnloadUnusedAssets;

2) 在場景載入的時候採用非增量的方式載入,這會清楚當前場景中的所有Objects,然後反射自動呼叫Resources.UnloadUnusedAssets

如果你不想管理這些assetbundle,unity推出了AssetBundle Manager,可以學習瞭解一下,此外Unity還推出了一些AssetBundle Browser Tool, 也可以學習瞭解一下。

9 校驗

CRC MD5 SHA1

相同點

CRC、MD5、SHA1都是通過對資料進行計算,來生成一個校驗值,該校驗值用來校驗資料的完整性。

不同點

1.演算法不同。CRC採用多項式除法,MD5和SHA1使用的是替換、輪轉等方法;

2.校驗值的長度不同。CRC校驗位的長度跟其多項式有關係,一般為16位或32位;MD5是16個位元組(128位);SHA1是20個位元組(160位);

3.校驗值的稱呼不同。CRC一般叫做CRC值;MD5和SHA1一般叫做雜湊值(Hash)或雜湊值;

4.安全性不同。這裡的安全性是指檢錯的能力,即資料的錯誤能通過校驗位檢測出來。CRC的安全性跟多項式有很大關係,相對於MD5和SHA1要弱很多;MD5的安全性很高,不過大概在04年的時候被山東大學的王小云破解了;SHA1的安全性最高。

5.效率不同,CRC的計算效率很高;MD5和SHA1比較慢。

6.用途不同。CRC一般用作通訊資料的校驗;MD5和SHA1用於安全(Security)領域,比如檔案校驗、數字簽名等。

10 

Unity Asset Bundle Browser tool

美朝最新動態:美朝雙方高階官員舉行會談  朝鮮表遺憾美方態度稱其“強盜”