Unity5系列资源管理AssetBundle——加载

上次我们进行了AssetBundle打包,现在我们还把打包的资源加载到我们的游戏中。
在加载之前,我们需要把打包好的Bundle包裹放到服务器上,如果没有,也可以使用XAMPP搭建本地服务器。

加载的AssetBundle文件是放在内存中的,所以如果没有很好的管理,会使游戏性能大打折扣,因此,我们在这里最好使用缓存策略。

我们的AssetBundle:

 1 using System;
 2 using UnityEngine;
 3  
 4 namespace MrCAssetFramework
 5 {
 6     public sealed class MrCAssetBundle
 7     {
 8         internal AssetBundle m_AssetBundle;
 9         internal string      m_AssetBundleName;
10         internal MrCAssetBundle(AssetBundle assetBundle,string name)
11         {
12             this.m_AssetBundle = assetBundle;
13             this.m_AssetBundleName = name;
14             this.m_ReferencedCount = 1;
15         }
16          
17         #region ReferenceCountManage
18         //yinyongjishujizhi
19         private int m_ReferencedCount;
20         public void Retain()
21         {
22             this.m_ReferencedCount++;
23         }
24         public void Release(){
25             this.m_ReferencedCount--;
26             //当引用计数为0时,卸载资源
27             if (this.m_ReferencedCount == 0) 
28             {
29                 this.m_AssetBundle.Unload (true);
30                 MrCAssetCache.FreeBundle(this.m_AssetBundleName);
31             }
32         }
33          
34         public int RetainCount()
35         {
36             return this.m_ReferencedCount;
37         }
38         #endregion
39          
40     }
41 }

AssetBundle管理:

  1 using System;
  2 using UnityEngine;
  3 using System.Collections;
  4 using System.Collections.Generic;
  5  
  6 namespace MrCAssetFramework
  7 {   
  8     public class MrCAssetManager:MonoBehaviour
  9     {
 10  
 11         #region Singleton
 12         private static GameObject       s_go_MrCAssetManager = null;
 13         private static MrCAssetManager  s_MrCAssetManager = null;
 14  
 15         public static MrCAssetManager DefaultAssetManager{
 16             get{
 17                 if (s_MrCAssetManager == null) {
 18                     s_go_MrCAssetManager = new GameObject ("LOAssetManager");
 19                     s_MrCAssetManager = s_go_MrCAssetManager.AddComponent<MrCAssetManager> ();
 20                 }
 21  
 22                 return s_MrCAssetManager;
 23             }
 24         }
 25  
 26         #endregion
 27  
 28         public  static string URI{ set; get;}
 29         public static string ManifestName{ set; get;}
 30         //无返回值泛型委托..
 31         public static Action<bool> InitBlock;
 32  
 33         public AssetBundleManifest manifest{ set; get;}
 34  
 35          36      ///<summary>
 37         /// To get the asset..
 38         /// </summary>
 39  
 40         /// <returns>The asset..</returns>
 41         public T GetAsset<T>(string assetbundlename,string assetname) where T:UnityEngine.Object
 42         {
 43             MrCAssetBundle lab = MrCAssetCache.GetBundleCache(assetbundlename);
 44  
 45             if (lab == null) {
 46                 return null;
 47             }
 48             else
 49             {
 50                 return lab.m_AssetBundle.LoadAsset<T>(assetname);
 51             }
 52         }
 53  
 54         IEnumerator LoadManifestBundle()
 55         {
 56             //缓存中已经存在请求的bundle,中止..
 57             if (MrCAssetCache.InCache(MrCAssetManager.ManifestName)) {
 58                 yield break;
 59             }
 60  
 61             // 通过网络下载AssetBundle
 62             WWW www = IsLoadAssetBundleAtInternal(MrCAssetManager.ManifestName);
 63             yield return www;
 64  
 65             this.manifest = this.GetAsset<AssetBundleManifest>(MrCAssetManager.ManifestName,"AssetBundleManifest");
 66             MrCAssetManager.InitBlock (this.manifest != null);
 67         }
 68         void Start()
 69         {
 70             StartCoroutine ("LoadManifestBundle");
 71         }
 72  
 73  
 74  
 75  
 76         #region 加载包裹系列函数
 77  
 78          79      ///<summary>
 80         /// 检查是否已经从网络下载
 81         /// </summary>
 82  
 83         protected WWW IsLoadAssetBundleAtInternal (string assetBundleName)
 84         {
 85             //已经存在了呀
 86             MrCAssetBundle bundle = MrCAssetCache.GetBundleCache(assetBundleName);
 87             if (bundle != null)
 88             {
 89                 //保留数加一次
 90                 bundle.Retain ();
 91                 return null;
 92             }
 93  
 94             //如果WWW缓存策略中包含有对应的关键字,则返回true
 95             if (MrCAssetCache.InCache (assetBundleName)) {
 96                 return null;
 97             }
 98  
 99             //创建下载链接
100             WWW www = new WWW(MrCAssetManager.URI + assetBundleName);
101             // 按版本号,按需要通过网络下载AssetBundle,一般在正式游戏版本中,不使用上面的,因为它会每次打开游戏重新下载
102             //WWW www = WWW.LoadFromCacheOrDownload(LOAssetManager.URI + assetBundleName, nowVersion);
103  
104             //加入缓存策略
105             MrCAssetCache.SetWWWCache(assetBundleName,www);
106  
107             return www;
108         }
109  
110  
111         IEnumerator LoadDependencies(string assetBundleName)
112         {
113             if (this.manifest == null) {
114                 yield return null;
115             }
116             // 获取依赖包裹
117             string[] dependencies = this.manifest.GetAllDependencies(assetBundleName);
118  
119             Debug.Log(dependencies.Length);
120  
121             if (dependencies.Length == 0)
122             {
123                 yield return null;
124             }
125  
126             // 记录并且加载所有的依赖包裹
127             MrCAssetCache.SetDependCache(assetBundleName, dependencies);
128  
129             for (int i = 0; i < dependencies.Length; i++) 
130             {
131                 yield return IsLoadAssetBundleAtInternal (dependencies [i]);
132             }
133         }
134  
135         136      /// <summary>
137         /// 加载资源包
138         /// </summary>
139  
140         IEnumerator LoadAssetBundle(string assetBundleName)
141         {
142             if (MrCAssetCache.InCache(assetBundleName)) {
143                 yield break;
144             }
145             // 通过网络下载AssetBundle
146             WWW www = IsLoadAssetBundleAtInternal(assetBundleName);
147             yield return www;
148  
149             // 通过网络加载失败,下载依赖包裹
150             yield return StartCoroutine(LoadDependencies(assetBundleName));
151         }
152  
153         154      ///<summary>
155         /// 异步加载资源
156         /// </summary>
157  
158         public IEnumerator LoadAssetAsync (string assetBundleName, string assetName, System.Type type)
159         {
160             //开始加载包裹
161             yield return StartCoroutine(LoadAssetBundle (assetBundleName));
162         }
163  
164         165      ///<summary>
166         /// 异步加载场景
167         /// </summary>
168  
169         public IEnumerator LoadLevelAsync (string assetBundleName, string levelName, bool isAdditive)
170         {
171             //加载资源包
172             yield return StartCoroutine(LoadAssetBundle (assetBundleName));
173  
174         }
175         #endregion
176  
177  
178         #region Update
179  
180         void Update()
181         {
182             MrCAssetCache.Update();
183         }
184         #endregion
185     }
186 }

缓存管理:

  1 using System;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4  
  5 namespace MrCAssetFramework
  6 {
  7     internal sealed class MrCAssetCache
  8     {
  9         #region 包裹缓存机制
 10         //创建缓存字典
 11         private static Dictionary<string, MrCAssetBundle> assetBundleCache;
 12         //缓存字典属性
 13         private static Dictionary<string, MrCAssetBundle> BundleCache
 14         {
 15             get{ 
 16                 if (assetBundleCache == null) {
 17                     assetBundleCache = new Dictionary<string, MrCAssetBundle> ();
 18                 }
 19                  
 20                 return assetBundleCache;
 21             }
 22         }
 23          
 24         //创建缓存WWW对象
 25         private static Dictionary<string, WWW> wwwCache;
 26         //创建缓存WWW对象属性
 27         private static Dictionary<string, WWW> WwwCache{
 28             get{ 
 29                 if (wwwCache == null) {
 30                     wwwCache = new Dictionary<string, WWW> ();
 31                 }
 32                  
 33                 return wwwCache;
 34             }
 35         }
 36         //创建依赖缓存对象
 37         private static Dictionary<string, string[]> dependCache;
 38         //创建依赖缓存属性
 39         private static Dictionary<string, string[]> DependCache
 40         {
 41             get{ 
 42                 if (dependCache == null) {
 43                     dependCache = new Dictionary<string, string[]> ();
 44                 }
 45                 return dependCache;
 46             }
 47         }
 48          
 49         private static Dictionary<string, string> errorCache;
 50         private static Dictionary<string,string> ErrorCache{
 51             get{ 
 52                 if (errorCache == null) {
 53                     errorCache = new Dictionary<string, string> ();
 54                 }
 55                 return errorCache;
 56             }
 57         }
 58  
 59          60      ///<summary>
 61         /// Instantiate the cache.
 62         /// </summary>
 63  
 64         /// <returns><c>true</c>, if cache was ined, <c>false</c> otherwise.</returns>
 65         /// <param name="assetbundlename">Assetbundlename.</param>
 66         internal static bool InCache(string assetbundlename)
 67         {
 68             return MrCAssetCache.BundleCache.ContainsKey(assetbundlename);
 69         }
 70         #endregion
 71  
 72  
 73         #region 卸载系列函数
 74          
 75          76      ///<summary>
 77         /// 卸载资源包和依赖包
 78         /// </summary>
 79  
 80         /// <param name="assetBundleName">Asset bundle name.</param>
 81         public static void UnloadAssetBundle(string assetBundleName)
 82         {
 83             UnloadAssetBundleInternal (assetBundleName);
 84             UnloadDependencies (assetBundleName);
 85         }
 86         internal static void UnloadDependencies(string assetBundleName)
 87         {
 88             string[] dependencies = null;
 89             //获取所有的依赖包名称
 90             if (!MrCAssetCache.DependCache.TryGetValue(assetBundleName, out dependencies) )
 91                 return;
 92              
 93             //卸载依赖包
 94             foreach(var dependency in dependencies)
 95             {
 96                 UnloadAssetBundleInternal(dependency);
 97             }
 98             //删除依赖缓存策略
 99             MrCAssetCache.DependCache.Remove(assetBundleName);
100         }
101          
102         internal static void UnloadAssetBundleInternal(string assetBundleName)
103         {
104             MrCAssetBundle bundle;
105             MrCAssetCache.BundleCache.TryGetValue(assetBundleName,out bundle);
106  
107             if (bundle == null)
108             {
109                 return;
110             }
111             bundle.Release ();
112         }
113         #endregion
114  
115         #region GetFunction
116         internal static WWW GetWWWCache(string key)
117         {
118             WWW www;
119              
120             MrCAssetCache.WwwCache.TryGetValue(key,out www);
121              
122             return www;
123         }
124         internal static void SetWWWCache(string key,WWW value)
125         {
126             MrCAssetCache.WwwCache.Add(key,value);
127         }
128          
129         internal static MrCAssetBundle GetBundleCache(string key)
130         {
131             MrCAssetBundle ab;
132              
133             MrCAssetCache.BundleCache.TryGetValue(key,out ab);
134              
135             return ab;
136         }
137         internal static void SetBundleCache(string key,MrCAssetBundle value)
138         {
139             MrCAssetCache.BundleCache.Add(key,value);
140         }
141  
142         internal static string[] GetDependCache(string key)
143         {
144             string[] depends;
145              
146             MrCAssetCache.DependCache.TryGetValue(key,out depends);
147              
148             return depends;
149         }
150         internal static void SetDependCache(string key,string[] value)
151         {
152             MrCAssetCache.DependCache.Add(key,value);
153         }
154  
155         internal static string GetErrorCache(string key)
156         {
157             string error;
158              
159             MrCAssetCache.ErrorCache.TryGetValue(key,out error);
160              
161             return error;
162         }
163         internal static void SetErrorCache(string key,string value)
164         {
165             MrCAssetCache.ErrorCache.Add(key,value);
166         }
167         #endregion
168  
169         internal static void FreeBundle(string key)
170         {
171             MrCAssetCache.BundleCache.Remove(key);
172         }
173  
174         #region Update
175  
176         internal static void Update()
177         {
178             // Collect all the finished WWWs.
179             var keysToRemove = new List<string>();
180             foreach (var keyValue in MrCAssetCache.WwwCache)
181             {
182                 WWW download = keyValue.Value;
183                 string m_bundleName = keyValue.Key;
184                  
185                 // 下载失败
186                 if (download.error != null)
187                 {
188                     MrCAssetCache.ErrorCache.Add(m_bundleName, download.error);
189                      
190                     keysToRemove.Add(m_bundleName);
191                      
192                     continue;
193                 }
194                  
195                 // 下载成功
196                 if(download.isDone)
197                 {
198                      
199                     MrCAssetCache.BundleCache.Add(m_bundleName, new MrCAssetBundle(download.assetBundle,m_bundleName));
200                      
201                     keysToRemove.Add(m_bundleName);
202                 }
203             }
204              
205             // 删除下载成功的WWW对象
206             foreach( var key in keysToRemove)
207             {
208                 WWW download = MrCAssetCache.WwwCache[key];
209                  
210                 MrCAssetCache.WwwCache.Remove(key);
211                  
212                 download.Dispose();
213             }
214         }
215  
216         #endregion
217     }
218 }

加载包裹中的场景:
新建一个场景,创建TestScript脚本,放到摄像机上。

 1 using UnityEngine;
 2 using System.Collections;
 3 //引入框架
 4 using MrCAssetFramework;
 5  
 6 public class TestScript : MonoBehaviour {
 7      
 8     /// <summary>
 9     /// 加载场景资源函数
10     /// </summary>
11     protected IEnumerator Load (string assetBundleName, string level)
12     {
13         IEnumerator b = da.LoadLevelAsync(assetBundleName, level, false);
14         yield return StartCoroutine(b);
15         Application.LoadLevel(level);
16     }
17  
18     MrCAssetManager da;
19     void Start () 
20     {
21         //指定统一资源标志符
22         MrCAssetManager.URI = "http://....../UnityFiles/AssetBundlesForBlog/";
23         //主配置文件
24         MrCAssetManager.ManifestName = "Others";
25         //加载成功后的操作代理
26         MrCAssetManager.InitBlock = ((bool bundleObj) => {
27             if (bundleObj) {
28                 //协程操作加载的AssetBundle包裹
29                 StartCoroutine (Load ("scenes/loaderscene.unity3d", "LoaderScene"));
30             }
31         });
32         //开始我们的一切
33         da = MrCAssetManager.DefaultAssetManager;
34     }
35 }

加载包裹中的游戏对象等资源到场景中:
在上面的测试脚本中,修改部分代码。

 1    /// <summary>
 2     /// 加载游戏对象资源函数
 3     /// </summary>
 4     protected IEnumerator LoadObj(string assetBundleName, string obj)
 5     {
 6         IEnumerator b = da.LoadAssetAsync(assetBundleName, obj, typeof(GameObject));
 7         yield return StartCoroutine(b);
 8         GameObject go = da.GetAsset<GameObject>(assetBundleName, obj);
 9         GameObject.Instantiate(go);
10     }
11 //-------------------------------------------------------------------------------
12         //加载成功后的操作代理
13         MrCAssetManager.InitBlock = ((bool bundleObj) => {
14             if (bundleObj) {
15                 //协程操作加载的游戏对象包裹
16                 StartCoroutine(LoadObj("prefabs/cube.prefab", "MyCube"));
17             }
18         });
原文地址:https://www.cnblogs.com/zhenlong/p/4859364.html