一個AssetBundle同時只能加載一次,所以實際使用中一般會伴隨着AssetBundle包的管理。
下面是一個簡單的AssetBundle管理器,提供了同步和異步加載函數:
using UnityEngine; using System.Collections; using System.Collections.Generic; public class AssetBundleManager { public static AssetBundleManager Instace { get { if (_instace == null) _instace = new AssetBundleManager(); return _instace; } } private static AssetBundleManager _instace = null; private AssetBundleManifest manifest = null; private Dictionary<string, AssetBundle> dicAssetBundle = new Dictionary<string, AssetBundle>(); // filename : Assets全路徑,比如Assets/Prefab/***.prefab public AssetBundle GetAssetBundle(string filePath) { AssetBundle ab = null; dicAssetBundle.TryGetValue(AssetsNameToBundleName(filePath), out ab); return ab; } // 加載manifest,用來處理關聯資源 public void LoadManifest() { AssetBundle bundle = AssetBundle.LoadFromFile(MainifestFilePath()); manifest = bundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); // 壓縮包直接釋放掉 bundle.Unload(false); bundle = null; } // filename : Assets全路徑,比如Assets/Prefab/***.prefab public AssetBundle Load(string filename) { string bundleName = AssetsNameToBundleName(filename); if (dicAssetBundle.ContainsKey(bundleName)) { return dicAssetBundle[bundleName]; } string[] dependence = manifest.GetAllDependencies(bundleName); for (int i = 0; i < dependence.Length; ++i) { LoadInternal(dependence[i]); } return LoadInternal(bundleName); } // filename : Assets全路徑,比如Assets/Prefab/***.prefab public IEnumerator LoadAsync(string filename) { string bundleName = AssetsNameToBundleName(filename); if (dicAssetBundle.ContainsKey(bundleName)) { yield break; } string[] dependence = manifest.GetAllDependencies(bundleName); for (int i = 0; i < dependence.Length; ++i) { yield return LoadInternalAsync(dependence[i]); } yield return LoadInternalAsync(bundleName); } public void Unload(string filename, bool force = false) { string bundleName = AssetsNameToBundleName(filename); AssetBundle ab = null; if (dicAssetBundle.TryGetValue(bundleName, out ab) == false) return; if (ab == null) return; ab.Unload(force); ab = null; dicAssetBundle.Remove(bundleName); } public void UnloadUnusedAssets() { Resources.UnloadUnusedAssets(); System.GC.Collect(); } public void Release() { foreach(var pair in dicAssetBundle) { var bundle = pair.Value; if(bundle != null) { bundle.Unload(true); bundle = null; } } dicAssetBundle.Clear(); } private AssetBundle LoadInternal(string bundleName) { if (dicAssetBundle.ContainsKey(bundleName)) { return dicAssetBundle[bundleName]; } AssetBundle bundle = AssetBundle.LoadFromFile(BundleNameToBundlePath(bundleName)); dicAssetBundle.Add(bundleName, bundle); return bundle; } private IEnumerator LoadInternalAsync(string bundleName) { if (dicAssetBundle.ContainsKey(bundleName)) { yield break; } AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(BundleNameToBundlePath(bundleName)); yield return req; dicAssetBundle.Add(bundleName, req.assetBundle); } // 名字依賴於存放目錄 private string MainifestFilePath() { return Application.dataPath + "/StreamingAssets/StreamingAssets"; } // Assets/Prefab/***.prefab --> assets.prefab.***.prefab.assetbundle private string AssetsNameToBundleName(string file) { string f = file.Replace('/', '.'); f = f.ToLower(); f += ".assetbundle"; return f; } // assets.prefab.***.prefab.assetbundle --> C:/***path***/assets.prefab.***.prefab.assetbundle private string BundleNameToBundlePath(string bundleFilename) { return System.IO.Path.Combine(Application.dataPath + "/StreamingAssets/", bundleFilename); } }
當然bundle也可以通過WWW或其他的方式來加載,這一塊Unity5到沒有什么變化,具體使用方式可以參考我以前的博客。