1:什麼是AssetBundle。
AssetBundle是從unity項目中打包出來的資源文件,可用於資源的更新等。AssetBundle支持3中格式的壓縮選擇,分別是LZMA,LZ4,無壓縮。默認是LZMA格式的壓縮,但是這樣雖然可以使資源文件大小大大縮小,利於下載,但是也有不利的一面,在使用時會先解壓再使用,所以會造成加載時間過長。
不壓縮格式資源包會比較大,但是加載時不需要解壓,所以加載時會更快。
2:怎麼創建AssetBundle.
在unity5.x中資源打包已經大大優化,打包過程比unity4.x大大簡化。可以自動打出依賴包。打包的過程有兩種,第一種是給要打包的資源起一個名字。如下圖
默認是不打包的,起名字後變爲
當想把多個物體打到一個包裏時,只需把多個物體設置成相同包名即可。設置好包名後,打包就容易的多了,打包代碼如下:(注意,在運行此腳本之前,您需要在Assets文件夾中創建“AssetBundles”文件夾)
using UnityEditor;
public class CreateAssetBundles
{
[MenuItem (“Assets/Build AssetBundles”)]
static void BuildAllAssetBundles ()
{
BuildPipeline.BuildAssetBundles (“Assets/AssetBundles”, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSXUniversal);
}
}
生成AssetBundle的時候每個文件會多生成一個Manifest文件,每個文件多生成的Manifest 文件是不需要的,其作用就是供開發人員查看AssetBundle 中的依賴關係等信息。但除了每個文件多生成的 Manifest 以外,根目錄下還會有一個與根目錄同名的AssetBundle 以及 Manifest 文件,通過運行時加載這個AssetBundle,可以得到一個 AssetBundleManifest 對象,然後就可以通過這個對象得到AssetBundle直接的依賴關係。在AssetBundle打包時,只打包這個Prefab(不指定BuildAssetBundleOptions.CompleteAssets和BuildAssetBundleOptionsCollectDependencies)的話是不能正確實例化的,因爲AssetBundle中的資源和Resource文件夾下資源是不會建立依賴關係的(腳本除外,因爲開啓BuildAssetBundleOptionsCollectDependencies 時,腳本依然不會打包到AssetBundle中)。所以會出現Mesh、Material等的丟失。
注意:
如果你只是給預製體起了名字而沒有給預製體依賴的資源起名字的話,打出來的包就會把依賴的資源默認跟預製體打包到同一個assetbundle裏,這樣就造成了如果兩個預製體使用同一份貼圖資源,那麼這個貼圖資源就會分別跟兩個預製體打包到一起,這就造成了內存的浪費。正確的做法是給貼圖資源單獨起一個名字,使其打包爲一個包,然後預製體再分別打包,這樣就會發現預製體的assetbundle包大大減小。但是,這樣的話還有一個問題,就是每次要先加載依賴的資源,然後才能加載實例化。
3:如何加載資源。
要加載一個資源A,必須先去加載它的所有依賴資源,要知道這個資源A依賴了哪些資源,必須先去加載AssetBundleManifest,通過AssetBundleManifest對象的GetAllDependencies(A)方法,獲取它依賴的所有資源。
依賴資源都加載了,就可以去真正加載資源A了。否則加載出來的物體就會材質丟失。
注意點:
1.資源A加載完了後,要記得Unload(false),資源A的依賴資源要在 資源A加載完成後,才能Unload(false),否則無法正常加載資源A
2.不Unload的話也可以,那就自己做一個字典記錄所有加載過的AssetBundle,還有它們的引用計數器。那樣就可以先判斷是否存在,然後再確定是否要去加載
加載的方式分爲兩種,一種是從文件加載,一種是從網絡加載。各種情況的加載如下;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class Loadassert : MonoBehaviour
{
string BundleURL = "file:///E:/Unity3D/modelpeizhi/Assets/AssetBundles/earth";
string AssetName = "earth";
//從文件夾里加載一個異步加載
public void LoadOne()
{
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/Sphere");
AssetBundleRequest gObject = bundle.LoadAssetAsync("sphere", typeof(GameObject));
GameObject obj = gObject.asset as GameObject;
Instantiate(obj);
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
}
//從文件夾里加載一個同步加載
public void LoadNoRequest()
{
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/Sphere");
UnityEngine.Object obj = bundle.LoadAsset("sphere");
Instantiate(obj);
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
}
//從文件夾里加載全部
public void loadAll()
{
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/Sphere");
foreach (UnityEngine.Object temp in bundle.LoadAllAssets())
{
Instantiate(temp);
}
bundle.Unload(false);
}
//從文件夾裏通過依賴關係加載
public void LoadManifest()
{
//加載那個打包時額外打出來的總包
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/AssetBundles");
// var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/AssetBundles.manifest");//不能這樣加載manifest。
AssetBundleManifest manifest = bundle.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
//AssetBundleManifest不是某個文件的名字,是固定的一個東西
string[] deps = manifest.GetAllDependencies("earth");
//earth是打出的包名
List<AssetBundle> depList = new List<AssetBundle>();
Debug.Log(deps.Length);
for (int i = 0; i < deps.Length; ++i)
{
AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/" + deps[i]);
depList.Add(ab);
}
AssetBundle cubeAb = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/earth");
GameObject org = cubeAb.LoadAsset("earth") as GameObject;
Instantiate(org);
cubeAb.Unload(false);
for (int i = 0; i < depList.Count; ++i)
{
depList[i].Unload(false);
}
bundle.Unload(true);
}
public void LoadNoManifest()
{
var bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/earth11");
AssetBundleRequest gObject = bundle.LoadAssetAsync("earth11", typeof(GameObject));
GameObject obj = gObject.asset as GameObject;
Instantiate(obj);
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
}
public void loadWWWNoStored()
{
StartCoroutine(_loadWWWNoStored());
}
public void LoadWWWStored()
{
StartCoroutine(_LoadWWWStored());
}
/// <summary>
/// -變量BundleURL的格式–如果爲UnityEditor本地:
/// —“file://”+“application.datapath”+“/文件夾名稱/文件名”
/// –如果爲服務器: —http://….
///-變量AssetName:
///–爲prefab或文件的名字。
/// </summary>
public IEnumerator _loadWWWNoStored()
{
// Download the file from the URL. It will not be saved in the Cache
using (WWW www = new WWW(BundleURL))
{
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
Instantiate(bundle.LoadAsset(AssetName));
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
public IEnumerator _LoadWWWStored()
{
// Wait for the Caching system to be ready
while (!Caching.ready)
yield return null;
// Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
using (WWW www = WWW.LoadFromCacheOrDownload(BundleURL, /*version*/ 0))
{
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
// Instantiate(bundle.mainAsset);
// Instantiate(bundle.LoadAsset(AssetName));
foreach (UnityEngine.Object temp in bundle.LoadAllAssets())
{
Instantiate(temp);
}
// Instantiate(bundle.LoadAllAssets());
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
}