上一篇我们分析了
从资源服务器下载资源(二) 接下来我们继续分析 LoadManager类。
当我们的任务下载完成后,我们需要对任务的委托进行回调到调用对象。
我们初步加入的委托有 complete、process、error ,接下来分别对这三个委托写相应的回调。
[csharp]
view plaincopy/// <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。
如下:
[csharp]
view plaincopy/**
* 任务下载的资源
* 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 中。
[csharp]
view plaincopy/// <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;
}
3.我们发现,似乎还没有对下载队列进行检测,即检测WWW类下载的状态。是已经下载完成了呢,还是下载出错。
这个时候我们需要一个定时器。
每隔一定时间对下载队列进行检测,我们在构造函数那里添加一个定时器。
[csharp]
view plaincopypublic LoadManager() {
Application.backgroundLoadingPriority = ThreadPriority.Low;
// add timer to check download queue
FrameTimerManager.getInstance().add(1, 0, CheckQueue);
}
其中的 CheckQueue() 函数是检测函数。
[csharp]
view plaincopy/// <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类即完成相应的功能。