在遊戲開發中,經常須要用到熱更新技術。好比:一個手機遊戲開發好後,用戶安裝到手機上。若是此時咱們要更新一個新的功能,若是沒有熱更新,那麼須要用戶卸載掉手機上的遊戲,而後安裝新的包,這樣作十分麻煩,並且容易流失用戶。這個時候就須要使用熱更新技術,讓用戶在手機上下載新的遊戲功能,不用從新下載就好了。下面使用的AssetBundle,嚴格意義上來講不算是熱更新,可是,它也能減小初始包體的大小。好比咱們開發一款棋牌遊戲,最初的包體只放出了鬥地主,在遊戲中,若是玩家還想玩麻將,那麼此時再下載麻將的相關資源。算法
1,AssetBundle是一個壓縮包包含模型、貼圖、預製體、聲音、甚至整個場景,能夠在遊戲運行的時候被加載; 服務器
2,AssetBundle自身保存着互相的依賴關係; 網絡
3,壓縮包可使用LZMA和LZ4壓縮算法,減小包大小,更快的進行網絡傳輸; 異步
4,把一些能夠下載內容放在AssetBundle裏面,能夠減小安裝包的大小;函數
1,它是一個存在於硬盤上的文件。能夠稱之爲壓縮包。這個壓縮包能夠認爲是一個文件夾,裏面包含了多個文件。這些文件能夠分爲兩類:serialized file 和 resource files。(序列化文件和源文件)佈局
serialized file:資源被打碎放在一個對象中,最後統一被寫進一個單獨的文件(只有一個)學習
resource files:某些二進制資源(圖片、聲音)被單獨保存,方便快速加載動畫
2,它是一個AssetBundle對象,咱們能夠經過代碼從一個特定的壓縮包加載出來的對象。這個對象包含了全部咱們當初添加到這個壓縮包裏面的內容,咱們能夠經過這個對象加載出來使用。ui
打包成AsserBundle,放到服務器spa
玩家用到相應的功能,再從服務器下載
1,指定資源的AssetBundle屬性
2,構建AssetBundle包
3,上傳AB包
4,加載AB包和包裏面的資源
1:首先咱們隨便作一個須要打包的資源,而後指定該資源的AssetBundle屬性。其中包名是須要指定的,後綴名能夠隨便寫,在學習的過程當中沒有什麼實際做用,在實際工做中根據公司須要來寫吧。
注意:若是包名寫成aaa,那麼會直接建立以aaa爲名的包。若是包名寫成aaa/bbb,那麼會建立名爲aaa的文件夾,在此文件夾下建立名爲bbb的包
2:打包以前,咱們要明白,打包只是在Edidor模式下運行,在遊戲運行過程當中沒有這個步驟。因此,建立一個文件夾名爲「Editor」,特別注意只能爲這個名字,而後在此文件夾下寫代碼來打包AssetBundle。在代碼中寫好方法後,將此方法放到Unity的菜單下來手動調用。
using UnityEditor; using System.IO; public class CreateAssetBundles { [MenuItem("Assets/Build AssetBundles")] static void BuildAllAssetBundles() { string dir = "AssetBundles"; if(Directory.Exists(dir) == false) { Directory.CreateDirectory(dir); } // BuildPipeline.BuildAssetBundles:打包的方法 // 參數:打包的路徑,Build的選項(下面專門說),打包的目標平臺 BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64); } }
3:在Unity菜單下,點擊該選項,進行打包,打包好後資源就存在了
咱們將場景中打包用到的資源都刪除,由於咱們這些資源已經打包好了,能夠直接加載這些資源。
注意:在加載資源的時候填入的名字,和包的名字可能不同,要看本身建立模型的時候是取得什麼名字
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LoadFromFile : MonoBehaviour { void Start () { // 加載ab包 AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/wood.unity3d"); // 加載資源 GameObject wallPrefab = ab.LoadAsset<GameObject>("Wood"); Instantiate(wallPrefab); } }
能夠看到,運行後也加載好了資源
1,邏輯實體分組
a,一個UI界面或者全部UI界面一個包(這個界面裏面的貼圖和佈局信息一個包)
b,一個角色或者全部角色一個包(這個角色裏面的模型和動畫一個包)
c,全部的場景所共享的部分一個包(包括貼圖和模型)
2,按照類型分組
全部聲音資源打成一個包,全部shader打成一個包,全部模型打成一個包,全部材質打成一個包
3,按照使用分組
把在某一時間內使用的全部資源打成一個包。能夠按照關卡分,一個關卡所須要的全部資源包括角色、貼圖、聲音等打成一個包。也能夠按照場景分,一個場景所須要的資源一個包
總結:
1,把常常更新的資源放在一個單獨的包裏面,跟不常常更新的包分離
2,把須要同時加載的資源放在一個包裏面
3,能夠把其餘包共享的資源放在一個單獨的包裏面 (依賴打包)
4,把一些須要同時加載的小資源打包成一個包
5,若是對於一個同一個資源有兩個版本,能夠考慮經過後綴來區分
依賴打包:
若是咱們有一份圖片資源,有兩個物體同時用到了這份資源,當單獨對這兩個物體進行打包的時候,打出的包中都會包含圖片資源。可是當咱們首先對圖片資源進行打包後,再對兩個物體進行打包,在打包的時候,引擎會自動檢索依賴,這個時候檢測到自身所依賴的圖片資源已經打包了,那麼這個時候自身就不會再對這個圖片資源進行打包。這樣,就減小了包體的大小。注意:在使用依賴打包後,若是A依賴了B的資源,那麼在使用A的時候,必須加載B,不然A實例化出來後材質會丟失。
在上面打包的時候函數有3個參數,其中第二個參數就是打包選項,用來控制打包時的壓縮方式。
1:BuildAssetBundleOptions.None:使用LZMA算法壓縮,壓縮的包更小,可是加載時間更長。使用以前須要總體解壓。一旦被解壓,這個包會使用LZ4從新壓縮。使用資源的時候不須要總體解壓。在下載的時候可使用LZMA算法,一旦它被下載了以後,它會使用LZ4算法保存到本地上。
2:BuildAssetBundleOptions.UncompressedAssetBundle:不壓縮,包大,加載快
3:BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4壓縮,壓縮率沒有LZMA高,可是咱們能夠加載指定資源而不用解壓所有
注意:使用LZ4壓縮,能夠得到能夠跟不壓縮想媲美的加載速度,並且比不壓縮文件要小。
1,AssetBundle.LoadFromMemoryAsync :從內存加載(異步加載)
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LoadFromFile : MonoBehaviour { IEnumerator Start () { string path = "AssetBundles/wood.unity3d"; // 第一種加載AB的方式 LoadFromMemoryAsync AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path)); yield return request; AssetBundle ab = request.assetBundle; // 加載資源 GameObject wallPrefab = ab.LoadAsset<GameObject>("Wood"); Instantiate(wallPrefab); } }
另外一種寫法:(同步加載)
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LoadFromFile : MonoBehaviour { void Start () { string path = "AssetBundles/wood.unity3d"; // 第一種加載AB的方式 LoadFromMemoryAsync AssetBundle ab = AssetBundle.LoadFromMemory(File.ReadAllBytes(path)); // 加載資源 GameObject wallPrefab = ab.LoadAsset<GameObject>("Wood"); Instantiate(wallPrefab); } }
注意:咱們上面保存到本地,因此最好直接用文件加載。演示從內存加載的時候,咱們首先把本地文件轉成字節流後再加載,在實際工做中不須要多這一步,怎麼合適怎麼作。
2,AssetBundle.LoadFromFile :從文件加載
下面是異步加載,同步加載在最上面開始的時候就寫過了
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LoadFromFile : MonoBehaviour { IEnumerator Start () { string path = "AssetBundles/wood.unity3d"; // 第二種加載AB的方式 LoadFromFile AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(path); yield return request; AssetBundle ab = request.assetBundle; // 加載資源 GameObject wallPrefab = ab.LoadAsset<GameObject>("Wood"); Instantiate(wallPrefab); } }
3,WWW.LoadFromCacheOrDownload (在unity2017後已廢棄,分紅2和4)
從本地加載
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LoadFromFile : MonoBehaviour { IEnumerator Start () { string path = "AssetBundles/wood.unity3d"; //第三種加載AB的方式 WWW while (Caching.ready == false) { yield return null; } //file:// file:/// WWW www = WWW.LoadFromCacheOrDownload(@"file:/H:\Unity Project WorkSpace\AssetBundleProject\39_AssetBundle\AssetBundles\wood.unity3d", 1); yield return www; if (string.IsNullOrEmpty(www.error) == false) { Debug.Log(www.error); yield break; } AssetBundle ab = www.assetBundle; // 加載資源 GameObject wallPrefab = ab.LoadAsset<GameObject>("Wood"); Instantiate(wallPrefab); } }
從服務器加載:這裏用的是本地服務器,本地服務器使用「NetBox2.exe」雙擊建立
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class LoadFromFile : MonoBehaviour { IEnumerator Start () { string path = "AssetBundles/wood.unity3d"; //第三種加載AB的方式 WWW while (Caching.ready == false) { yield return null; } //file:// file:/// WWW www = WWW.LoadFromCacheOrDownload(@"http://localhost/AssetBundles/wood.unity3d", 1); yield return www; if (string.IsNullOrEmpty(www.error) == false) { Debug.Log(www.error); yield break; } AssetBundle ab = www.assetBundle; // 加載資源 GameObject wallPrefab = ab.LoadAsset<GameObject>("Wood"); Instantiate(wallPrefab); } }
4,UnityWebRequest:從服務器加載
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEngine.Networking; public class LoadFromFile : MonoBehaviour { IEnumerator Start () { //第四種方式 使用UnityWebRequest // 下面2個一個從本地,一個從服務器 //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 ab = DownloadHandlerAssetBundle.GetContent(request); AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle; // 加載資源 GameObject wallPrefab = ab.LoadAsset<GameObject>("Wood"); Instantiate(wallPrefab); } }
以上只是簡單的使用方法,更多的使用方法須要看官方手冊!!!