资源管理器核心的集合一共有三个:
1.等待加载的资源队列
private Queue <ResLoadRequest> m_QueWaitLoadAsset = new Queue< ResLoadRequest
2.当前正在加载的资源列表
private List <ResLoadRequest> m_LstLoadingAsset = new List< ResLoadRequest
3.已经完成加载的资源字典
private Dictionary <string, AssetPack > m_DicLoadedAsset = new Dictionary< string , 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 }