【学习笔记】 多线程资源管理器(附流程图附源码)

《奇怪的大冒险》教程视频连接:
http://www.taikr.com/course/222
笔记结合了前7课的视频内容,感谢新总提供的免费视频
PS:部分字段、属性和方法的命名与视频教程中有出入。

资源管理器核心的集合一共有三个:

1.等待加载的资源队列
private Queue <ResLoadRequestm_QueWaitLoadAsset = new QueueResLoadRequest >();
2.当前正在加载的资源列表
private List <ResLoadRequestm_LstLoadingAsset = new ListResLoadRequest >();
3.已经完成加载的资源字典
private Dictionary <stringAssetPack > m_DicLoadedAsset = new Dictionarystring , AssetPack >();

资源管理器的核心思想就是通过操作这三个集合,进行资源的加载,持有及释放。
三个集合的类型,可以看到明显的差异。
集合 <等待加载> 和 <正在加载> 的元素类型均为 ResLoadRequest类(资源加载数据类)
集合 <完成加载> 的元素类型为 AssetPack类(资源包类)

先从几个集合的转换,做个简要介绍
然后是资源管理器的流程图:
框架层级的东西,单纯看代码比较难以理解,所以我比较喜欢画图记忆,大体原理掌握了,自己也可以写出来了~!
在这基础上还可以增加AssetBundle的资源管理器。

另附本次学习的资源管理器代码
  1 // **********************************************************************
  2 // 
  3 // 文件名(File Name):             ResMgr.cs
  4 // 
  5 // 作者(Author):                 沐小沫
  6 // 
  7 // 日期(Create Date):             2015-07-10
  8 // 
  9 // **********************************************************************
 10 
 11 using UnityEngine;
 12 using System.Collections;
 13 using System;
 14 using System.Collections.Generic;
 15 using UnityEngine.EventSystems;
 16 
 17 public class ResMgr : MonoBehaviour
 18 {
 19     private static ResMgr m_Instance = null;                // 静态实例
 20     /// <summary>
 21     /// 获取静态实例
 22     /// </summary>
 23     /// <returns>静态实例</returns>
 24     public static ResMgr GetInstance()
 25     {
 26         return m_Instance;
 27     }
 28 
 29     private GameObject m_CachedGameObject;                  // 缓存对象
 30     private GameObject CachedGameObject
 31     {
 32         get
 33         {
 34             if (null == m_CachedGameObject && null != m_Instance)
 35             {
 36                 m_CachedGameObject = this.gameObject;
 37             }
 38 
 39             return m_CachedGameObject;
 40         }
 41     }
 42 
 43     private static int m_ProcessorCount = 0;                // 线程数量
 44     private static int ProcessorCount
 45     {
 46         set { m_ProcessorCount = Mathf.Clamp(value, 1, 8); }
 47         get { return m_ProcessorCount; }
 48     }
 49 
 50     void Awake()
 51     {
 52         ProcessorCount = SystemInfo.processorCount;
 53         DontDestroyOnLoad(CachedGameObject);
 54         m_Instance = this;
 55     }
 56 
 57     /// <summary>
 58     /// 当前正在加载的资源列表
 59     /// </summary>
 60     private List<ResLoadRequest> m_LstLoadingAsset = new List<ResLoadRequest>();
 61 
 62     /// <summary>
 63     /// 等待加载的资源队列
 64     /// </summary>
 65     private Queue<ResLoadRequest> m_QueWaitLoadAsset = new Queue<ResLoadRequest>();
 66 
 67     /// <summary>
 68     /// 已经完成加载的资源字典
 69     /// </summary>
 70     private Dictionary<string, AssetPack> m_DicLoadedAsset = new Dictionary<string, AssetPack>();
 71 
 72    
 73     /// <summary>
 74     /// 从Resources中加载一个资源
 75     /// </summary>
 76     /// <param name="assetName">资源名称</param>
 77     /// <param name="assetType">资源类型</param>
 78     /// <param name="loadListeners">加载完成的监听接口</param>
 79     /// <param name="isKeepInMemory">是否常驻内存</param>
 80     public void LoadAsset(string assetName, ILoadListeners loadListeners, Type assetType = null, bool isKeepInMemory = false)
 81     {
 82         if(string.IsNullOrEmpty(assetName))
 83         {
 84             if (null != loadListeners)
 85             {
 86                 loadListeners.Failure();
 87             }
 88             return;
 89         }
 90 
 91         if (m_DicLoadedAsset.ContainsKey(assetName))
 92         {
 93             if (null != loadListeners)
 94             {
 95                 loadListeners.Success(m_DicLoadedAsset[assetName].m_Asset);
 96             }
 97             return;
 98         }
 99 
100         for (int i = 0; i < m_LstLoadingAsset.Count; i++)
101         {
102             ResLoadRequest request = m_LstLoadingAsset[i];
103             if (request.m_AssetName.Equals(assetName))
104             {
105                 request.AddListeners(loadListeners);
106                 return;
107             }
108         }
109 
110         foreach (ResLoadRequest request in m_QueWaitLoadAsset)
111         {
112             if (request.m_AssetName.Equals(assetName))
113             {
114                 request.AddListeners(loadListeners);
115                 return;
116             }
117         }
118 
119         ResLoadRequest loadRequest = new ResLoadRequest(assetName, isKeepInMemory, assetType);
120         loadRequest.AddListeners(loadListeners);
121         m_QueWaitLoadAsset.Enqueue(loadRequest);
122     }
123 
124     /// <summary>
125     /// 从资源队列中处理待加载的资源
126     /// </summary>
127     public void Update()
128     {
129         if(m_LstLoadingAsset.Count > 0)
130         {
131             for(int i = m_LstLoadingAsset.Count - 1; i >= 0 ; i--)
132             {
133                 if (m_LstLoadingAsset[i].IsLoadedDone)
134                 {
135                     LoadAssetFinish(m_LstLoadingAsset[i]);
136                     m_LstLoadingAsset.RemoveAt(i);
137                 }
138             }
139         }
140 
141         while (m_LstLoadingAsset.Count < ProcessorCount && m_QueWaitLoadAsset.Count > 0)
142         {
143             ResLoadRequest request = m_QueWaitLoadAsset.Dequeue();
144             m_LstLoadingAsset.Add(request);
145             request.LoadAsync();
146         }
147     }
148 
149     /// <summary>
150     /// 资源加载完毕
151     /// </summary>
152     void LoadAssetFinish(ResLoadRequest request)
153     {
154         if(null != request)
155         {
156             for (int i = 0; i < request.m_LstListeners.Count; i++)
157             {
158                 ILoadListeners listeners = request.m_LstListeners[i];
159 
160                 if (null != listeners)
161                 {
162                     if (null != request.m_Request && null != request.Asset)
163                     {
164                         listeners.Success(request.Asset);
165 
166                         AssetPack pack = new AssetPack(request.m_AssetType, request.m_IsKeepInMemory);
167                         pack.m_Asset = request.Asset;
168                         m_DicLoadedAsset.Add(request.m_AssetName, pack);
169                     }
170                     else
171                     {
172                         listeners.Failure();
173                     }
174                 }
175             }
176 
177         }
178     }
179     
180     /// <summary>
181     /// 释放指定的资源
182     /// </summary>
183     /// <param name="assetName">资源名字</param>
184     /// <param name="canRealseKeepInMemory">是否可以释放常驻内存的资源</param>
185     public void ReleaseAsset(string assetName, bool canRealseKeepInMemory)
186     {
187         if (!m_DicLoadedAsset.ContainsKey(assetName))
188         {
189             return;
190         }
191 
192         if (m_DicLoadedAsset[assetName].m_IsKeepInMemory && !canRealseKeepInMemory)
193         {
194             return;
195         }
196 
197         m_DicLoadedAsset[assetName] = null;
198         m_DicLoadedAsset.Remove(assetName);
199 
200         Resources.UnloadUnusedAssets();
201     }
202 
203     /// <summary>
204     /// 释放全部资源
205     /// </summary>
206     public void ReleaseAllAsset()
207     {
208         foreach (KeyValuePair<string, AssetPack> pair in m_DicLoadedAsset)
209         {
210             m_DicLoadedAsset[pair.Key] = null;
211         }
212 
213         m_DicLoadedAsset.Clear();
214         Resources.UnloadUnusedAssets();
215     }
216 
217 #region 资源加载数据类
218     /// <summary>
219     /// 加载类
220     /// </summary>
221     public class ResLoadRequest
222     {
223         /// <summary>
224         /// 资源名称
225         /// </summary>
226         public string m_AssetName;
227 
228         /// <summary>
229         /// 资源类型
230         /// </summary>
231         public Type m_AssetType;
232 
233         /// <summary>
234         /// 监听接口
235         /// </summary>
236         public List<ILoadListeners> m_LstListeners = new List<ILoadListeners>();
237 
238         /// <summary>
239         /// 加载资源请求
240         /// </summary>
241         public ResourceRequest m_Request;
242 
243         /// <summary>
244         /// 是否常驻内存
245         /// </summary>
246         public bool m_IsKeepInMemory;
247 
248         /// <summary>
249         /// 重载构造函数
250         /// </summary>
251         /// <param name="assetName">资源名称</param>
252         /// <param name="isKeepInMemory">是否常驻内存</param>
253         /// <param name="assetType">资源类型</param>
254         public ResLoadRequest(string assetName, bool isKeepInMemory, Type assetType)
255         {
256             this.m_AssetName = assetName;
257             this.m_IsKeepInMemory = isKeepInMemory;
258             this.m_AssetType = assetType;
259         }
260 
261         /// <summary>
262         /// 添加一个监听到监听列表
263         /// </summary>
264         /// <param name="listeners">监听接口</param>
265         public void AddListeners(ILoadListeners listeners)
266         {
267             if (listeners == null)
268             {
269                 return;
270             }
271 
272             if(!m_LstListeners.Contains(listeners))
273             {
274                 m_LstListeners.Add(listeners);
275             }
276         }
277 
278         /// <summary>
279         /// 加载到的资源
280         /// </summary>
281         public UnityEngine.Object Asset
282         {
283             get
284             {
285                 if (null != m_Request && null != m_Request.asset)
286                 {
287                     return m_Request.asset;
288                 }
289                 else
290                 {
291                     return null;
292                 }
293             }
294         }
295 
296         /// <summary>
297         /// 当前是否已经加载完成
298         /// </summary>
299         public bool IsLoadedDone
300         {
301             get { return (null != m_Request && m_Request.isDone); }
302         }
303 
304         /// <summary>
305         /// 异步加载资源
306         /// </summary>
307         public void LoadAsync()
308         {
309             if (null == m_AssetType)
310             {
311                 m_AssetType = typeof(GameObject);
312             }
313 
314             m_Request = Resources.LoadAsync(m_AssetName, m_AssetType);
315         }
316     }
317 
318     /// <summary>
319     /// 资源包
320     /// </summary>
321     public class AssetPack
322     {
323         /// <summary>
324         /// 资源类型
325         /// </summary>
326         public Type m_AssetType;
327 
328         /// <summary>
329         /// 是否常驻内存
330         /// </summary>
331         public bool m_IsKeepInMemory;
332 
333         /// <summary>
334         /// 资源
335         /// </summary>
336         public UnityEngine.Object m_Asset;
337 
338         public AssetPack(Type assetType, bool isKeepInMemory)
339         {
340             m_AssetType = assetType;
341             m_IsKeepInMemory = isKeepInMemory;
342         }
343     }
344 #endregion
345 
346 #region 加载资源完成后监听接口
347 
348     public interface ILoadListeners
349     {
350         /// <summary>
351         /// 加载成功
352         /// </summary>
353         /// <param name="asset">资源</param>
354         void Success(UnityEngine.Object asset);
355 
356         /// <summary>
357         /// 加载失败
358         /// </summary>
359         void Failure();
360     }
361 
362 #endregion
363 }

 

posted @ 2015-07-14 20:05  沐小沫  阅读(1793)  评论(1编辑  收藏  举报