1. 程式人生 > >unity 中 AssetBundle打包及使用總結(WebGL)

unity 中 AssetBundle打包及使用總結(WebGL)

資源打包,教程很多。但,適合自己專案的打包又有幾個?None
打包注意點:
(1)資源儘量分資料夾放置,便於打包資源的管理
(2)打包相對獨立資源
(3)打包時,儘量只打包素材,且大小控制在10M左右,避免影響下載速度
(4)打入包的例項化物體,在其他指令碼被引用的時候,通過查詢方式(名稱會多個“(clone)”)。且例項化一定要比引用要早,避免出現訪問空物件的問題。儘量例項化在Awake中,引用在Start中。
(5)共用資源、私有資源配合打包
共有資源打包,可用初始化程式碼統一管理。比如房間、人、治療巾等。但是需要進入程式即開始非同步下載,以免影響各常見的使用。
私有資源在進入對應場景時再下載,避免資源浪費;在場景解除安裝時,一定解除安裝私有資源。
(6)如果有 AssetBoudle的使用,保證在釋出時,不勾選“Strip Engine Code*”,但是無用程式碼一定清理乾淨。

WebGl平臺的資源打包:
一、標記資源(AssetBoudle名稱,如xx.ab )
二、建立以下程式碼,放入“Asset—Editor”路徑中

[MenuItem("AssetsBoundle/Build AssetBoudles")]
    static void BuildAllAssetBoundles()
    {
        string strDir = "AssetBoundles";
    if(Directory.Exists(strDir)==false)
    {
        Directory.CreateDirectory(strDir);
    }
    BuildPipeline.BuildAssetBundles(strDir, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.WebGL);
 }

核心是BuildAssetBundles(strDir, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.WebGL);

採用Chunk的編譯方法,是為了WebGl的下載、編譯快速。平臺要選擇WebGL。
三、已打包的內容放置到伺服器。
有可能伺服器需要設定下(1) 檔案格式的型別(2)跨域訪問 (3)訪問許可權
四、執行程式時,啟動協程,下載、載入對應資源

    public List<string> bundleToLoadList = new List<string>();  //要下載、載入的所有資源路徑
    public List<AssetBundle> bundlesLoadedList = new List<AssetBundle>(); //已下載的資源列表
    Dictionary<string, Object> allObjs=new Dictionary<string,Object>();  //所有預設體字典
    List<Object> objsList = new List<Object>(); //所有預設體
    public string 
[email protected]
"http://192.168.1.110:80/boundles/"; //下載地址 void Start () { StartCoroutine(load()); } IEnumerator load() { foreach(string strBundle in bundleToLoadList) { string strurl = strABUrl + strBundle; Debug.Log(strurl+" Time:"+Time.time); //用using的方式,為了讓web自行釋放 using (WWW bundleW = new WWW(strurl)) { yield return bundleW; //下載過程 if (bundleW.isDone && bundleW.error == null) { Debug.Log(bundleW.assetBundle.name + " downloaded success!" + " Time:" + Time.time); AssetBundle assetBd = bundleW.assetBundle; bundlesLoadedList.Add(assetBd); Debug.Log("bundle name:" + assetBd.name); Object[] objs = assetBd.LoadAllAssets(); //載入過程 Debug.Log("loaded success!" + " Time:" + Time.time); foreach (Object obj in objs) { if (!allObjs.ContainsKey(obj.name)) { if (obj.GetType() == typeof(GameObject)) allObjs.Add(obj.name, obj); } else Debug.Log("aready exist asset :" + obj.name + " type:" + obj.GetType() + " with type:" + allObjs[obj.name].GetType()); objsList.Add(obj); } } else Debug.Log("down load failed!--" + strBundle); } } } //強制解除安裝所有資源 public void ForceUnLoadAll() { if (bundlesLoadedList.Count == 0) return; for (int i = 0; i < bundlesLoadedList.Count;i++ ) { if(bundlesLoadedList[i]!=null) { bundlesLoadedList[i].Unload(true); bundlesLoadedList[i] = null; } } for (int i = 0; i < objsList.Count; i++) { objsList[i] = null; } objsList.Clear(); foreach (KeyValuePair<string, Object> obj in allObjs) { allObjs[obj.Key] = null; } allObjs.Clear(); }

五、在需要例項化的地方,進行例項化

 public List<string> gameobjectsToInstantiate = new List<string>(); //需要的載入預設體的名稱列表
  BundleLoadMgr bundleLoadMgr = null; //資源載入器物件(上面程式碼的類)
  void Awake () {
        bundleLoadMgr = GameObject.Find("BundleLoadMgr").GetComponent<BundleLoadMgr>();
        StartCoroutine(InstanceInstantiate());
       // InstanceInOneLine();
	}
   IEnumerator InstanceInstantiate()
    {
        if (bundleLoadMgr != null)
        {
            foreach (string strObj in gameobjectsToInstantiate)
            {
                Object obj = null; 
                ////確保載入上後,再開始初始化所有物體
                while(obj==null)
                {
                  obj=   bundleLoadMgr.GetGameobjectAssetByName(strObj);
                  yield return obj;
                }
                    yield return Instantiate(obj);
            }
        }
    }

協程例項化的方式,可能會造成其他指令碼呼叫到本預設體時為空的問題。也可以在主執行緒例項化這些預設體,但是如果之前未下載完成的話,可能會卡住執行緒。兩種方法各有利弊。儘量讓預設體有自己的獨立性,最起碼預設體外的儘量少引用該預設體。

最後記著銷燬無用的資源。