上一篇我们分析了 从资源服务器下载资源(二) 接下来我们继续分析 LoadManager类。
当我们的任务下载完成后,我们需要对任务的委托进行回调到调用对象。
我们初步加入的委托有 complete、process、error ,接下来分别对这三个委托写相应的回调。
/// <summary> /// 下载错误回调 /// </summary> public void ErrorDelegateHandle(LoadRequest request) { if (request.errorFunction != null) { int count = request.errorFunction.GetInvocationList().GetLength(0); for (int i = 0; i < count; i++) { LoadRequest.ErrorDelegate errorFunc = (LoadRequest.ErrorDelegate)request.errorFunction.GetInvocationList()[i]; try { errorFunc.Invoke(request); } catch (Exception e) { Debug.LogWarning("exception:" + e.Message); } } } } /// <summary> /// 下载进度回调 /// </summary> public void ProcessDelegateHandle(LoadRequest request) { if (request.processFunction != null) { int count = request.processFunction.GetInvocationList().GetLength(0); for (int i = 0; i < count; i++) { LoadRequest.ProcessDelegate processFunc = (LoadRequest.ProcessDelegate)request.processFunction.GetInvocationList()[i]; try { processFunc.Invoke(request.wwwObject.progress, request.wwwObject.bytesDownloaded); } catch (Exception e) { Debug.LogWarning("exception:" + e.Message); } } } } /// <summary> /// 任务下载完成回调 /// </summary> /// <param name="request"></param> /// <param name="param"></param> public void CompleteDelegateHandle(LoadRequest request, LoadParam param) { if (request.completeFunction != null) { int count = request.completeFunction.GetInvocationList().GetLength(0); for (int i = 0; i < count; i++) { if (i < request.customParams.Count) { param.param = request.customParams[i]; } LoadRequest.DownCompleteDelegate completeFunc = (LoadRequest.DownCompleteDelegate)request.completeFunction.GetInvocationList()[i]; try { completeFunc.Invoke(param); } catch (Exception exception) { Debug.LogWarning("exception:" + exception.Message); } } } }
1. 在上面我们注意到有一个陌生的类 LoadParam. 这个类是用来做什么的呢?
很简单,因为我们下载完成后会进行存储所有的下载结果,方便后续下载相同资源时可以马上调用。所以我们需要专门的对象来存放。
我们把所有类型写到一个类里面,然后标注好该对象的对应URL、filetype。
如下:
/** * 任务下载的资源 * create by chensh 2014.10.27 10:35 */ using UnityEngine; using System.Collections; namespace AssemblyCSharp { public class LoadParam { // 加载的文件类型 public string fileType; // 加载的路径 public string url; // 自定义参数 public object param = null; // 图片 public Texture2D texture2D; // 文本 public string text = ""; // unity3d格式文件,目前针对场景打包的unity3d格式文件 public AssetBundle assetBundle = null; // json文件 public string jsonData; // 二进制文件 public byte[] byteArr; // 音频文件 public AudioClip audioClip; // 模块资源打包格式文件 public UIAtlas uiAtlas; // fbx打包的文件对象 public UnityEngine.Object mainAsset; // font文件 public UIFont font; } }
2. 此时我们需要一个函数。来解析下载完后的资源,并保存到 LoadParam 中。
/// <summary> /// 解析下载内容 /// </summary> public LoadParam ParseLoadParamFromLoadRequest(LoadRequest request) { LoadParam param = new LoadParam(); param.url = request.requestURL; param.priority = request.priotiry; // 为何param需要记录优先级? param.fileType = request.fileType; switch (request.fileType) { case LoadFileType.IMAGE: try { param.texture2D = request.wwwObject.texture; param.texture2D.Compress(false); // compress 有何影响 } catch (Exception exception) { Debug.LogWarning("read texture2d error:" + request.requestURL +"\n" + exception.Message); } break; case LoadFileType.TXT: try { param.text = request.wwwObject.text; } catch (Exception exception) { Debug.LogWarning("read text error:" + request.requestURL + "\n" + exception.Message); } break; case LoadFileType.UNITY3D: try { if (request.wwwObject.assetBundle != null) { param.assetBundle = request.wwwObject.assetBundle; } } catch (Exception exception) { Debug.LogWarning("read assetBundle error:" + request.requestURL + "\n" + exception.Message); } break; case LoadFileType.MODULE_RESOURCE: try { UnityEngine.Object[] data = request.wwwObject.assetBundle.LoadAll(); int length = data.Length; for (int i = 0; i < length; i++) { if (data[i] is GameObject) { param.uiAtlas = (data[i] as GameObject).GetComponent<UIAtlas>(); break; } } request.wwwObject.assetBundle.Unload(false); } catch (Exception exception) { Debug.LogWarning("read uiatlas error:" + request.requestURL + "\n" + exception.Message); } break; case LoadFileType.JSON: try { param.jsonData = request.wwwObject.text.Trim(); } catch (Exception exception) { Debug.LogWarning("read json error:" + request.requestURL + "\n" + exception.Message); } break; case LoadFileType.FBX: try { param.mainAsset = request.wwwObject.assetBundle.mainAsset; } catch (Exception exception) { Debug.LogWarning("read fbx error:" + request.requestURL + "\n" + exception.Message); } break; case LoadFileType.BINARY: case LoadFileType.BINARY_BG: try { param.byteArr = request.wwwObject.bytes; } catch (Exception exception) { Debug.LogWarning("read binary error:" + request.requestURL + "\n" + exception.Message); } break; case LoadFileType.AUDIO: try { UnityEngine.Object[] data = request.wwwObject.assetBundle.LoadAll(); int length = data.Length; for (int i = 0; i < length; i++) { if (data[i] is AudioClip) { param.audioClip = data[i] as AudioClip; break; } } request.wwwObject.assetBundle.Unload(false); } catch (Exception exception) { Debug.LogWarning("read audio error:" + request.requestURL + "\n" + exception.Message); } break; case LoadFileType.FONT: try { UnityEngine.Object[] data = request.wwwObject.assetBundle.LoadAll(); int length = data.Length; for (int i = 0; i < length; i++) { if (data[i] is UnityEngine.Transform) { param.font = (data[i] as UnityEngine.Transform).GetComponent<UIFont>(); break; } } request.wwwObject.assetBundle.Unload(false); } catch (Exception exception) { Debug.LogWarning("read font error:" + request.requestURL + "\n" + exception.Message); } break; } return param; }
这个时候我们需要一个定时器。
每隔一定时间对下载队列进行检测,我们在构造函数那里添加一个定时器。
public LoadManager() { Application.backgroundLoadingPriority = ThreadPriority.Low; // add timer to check download queue FrameTimerManager.getInstance().add(1, 0, CheckQueue); }
/// <summary> /// 定时器下,在每帧对下载队列进行检测 /// 如果下载有问题,或者超时,则清除 /// 如果下载完成,则解析下载结果,并进入completeDict中 /// </summary> public void CheckQueue() { if (!isLoading) return; foreach (KeyValuePair<string, LoadRequest> pair in loadDict) { LoadRequest request = pair.Value; request.loadTotalFrames++; // deal error if ((request.wwwObject != null && request.wwwObject.error != null) || request.isTimeOut) { if (request.requestURL.Contains(".apk") || request.requestURL.Contains(".ipa")) { return; } request.alreadyDeal = true; loadDict.Remove(request.requestURL); ErrorDelegateHandle(request); if (request.isTimeOut) { Debug.LogWarning("Load time out:" + request.requestURL); } else { Debug.LogWarning("Load error:" + request.requestURL); } MoveRequestFromWaitDictToLoadDict(); break; } // if (!request.alreadyDeal) { ProcessDelegateHandle(request); // if done if (request.wwwObject != null && request.wwwObject.isDone) { LoadParam param = ParseLoadParamFromLoadRequest(request); if (request.fileType != LoadFileType.BINARY) { completeDict.Add(request.requestURL, param); } // CompleteDelegateHandle(request, param); // request.alreadyDeal = true; loadDict.Remove(request.requestURL); MoveRequestFromWaitDictToLoadDict(); break; } } } }
至此,我们的LoadManager类即完成相应的功能。