承接上一篇:http://blog.csdn.net/lyh916/article/details/51146693
上一篇基本实现了更新下载,很多时候,我们还需要将更新文件数,下载速度等信息显示在界面上,所以这篇就说下怎么做。
效果图:
Ps:上面的下载速度为Infinity(无穷大),具体原因不明,估计是我使用的是编辑器链接本地服务器,而且更新的文件很小,所以就快得飞起吧!
分析:
这里我把它分为两部分:
a.信息的获取:其实上面显示的信息,都可以通过GameManager.cs获取到。
b.信息的显示:在GameManager.cs中,我们可以发现,当获取到消息后,就会通过facade.SendMessageCommand把消息进行发送,然后被AppView.cs进行捕获处理。
因此目标就很明确了:修改GameManager和AppView。
1.首先,看下facade.SendMessageCommand,它可以发送各种的消息,消息的定义在NotiConst.cs。这里我们把消息的种类扩充一下。
using UnityEngine;
using System.Collections;
public class NotiConst
{
///
/// Controller层消息通知
///
public const string START_UP = "StartUp"; //启动框架
public const string DISPATCH_MESSAGE = "DispatchMessage"; //派发信息
///
/// View层消息通知
///
//解包要展示的相关参数
public const string EXTRACT_FILE_NAME = "EXTRACT_FILE_NAME"; //解包文件名
public const string EXTRACT_FINISH_ONE = "EXTRACT_FINISH_ONE"; //解包完一个文件
public const string EXTRACT_ALL_COUNT = "EXTRACT_ALL_COUNT"; //解包总文件数
//更新要展示的相关参数
public const string UPDATE_SPEED = "UPDATE_SPEED"; //下载速度
public const string UPDATE_FILE_NAME = "UPDATE_FILE_NAME"; //下载文件名
public const string UPDATE_FINISH_ONE = "UPDATE_FINISH_ONE"; //下载完一个文件
public const string UPDATE_ALL_COUNT = "UPDATE_ALL_COUNT"; //下载总文件数
//线程相关
public const string THREAD_EXTRACT = "THREAD_EXTRACT"; //线程解包
public const string THREAD_DOWNLOAD = "THREAD_DOWNLOAD"; //线程下载
}
2.然后就是准备好解包和更新的参数,并把这些参数发送出去。
修改GameManager.cs
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using LuaInterface;
using System.Reflection;
using System.IO;
namespace LuaFramework {
public class GameManager : Manager {
protected static bool initialize = false;
private List downloadFiles = new List();
///
/// 初始化游戏管理器
///
void Awake() {
Init();
}
///
/// 初始化
///
void Init() {
if (AppConst.ExampleMode) {
InitGui();
}
DontDestroyOnLoad(gameObject); //防止销毁自己
CheckExtractResource(); //释放资源
Screen.sleepTimeout = SleepTimeout.NeverSleep;
Application.targetFrameRate = AppConst.GameFrameRate;
}
///
/// 初始化GUI
///
public void InitGui() {
string name = "UI Root";
GameObject gui = GameObject.Find(name);
if (gui != null) return;
GameObject prefab = Util.LoadPrefab(name);
gui = Instantiate(prefab) as GameObject;
gui.name = name;
}
///
/// 释放资源
///
public void CheckExtractResource() {
hadExtractResource = Directory.Exists(Util.DataPath) &&
Directory.Exists(Util.DataPath + "lua/") && File.Exists(Util.DataPath + "files.txt");
if (hadExtractResource || AppConst.DebugMode)
{
ResManager.initialize(OnResourceInited);
//StartCoroutine(OnUpdateResource());//在第二次解包后就更新
return; //文件已经解压过了,自己可添加检查文件列表逻辑
}
StartCoroutine(OnExtractResource()); //启动释放协成
}
bool hadExtractResource;
bool firstExtractResource = true;
IEnumerator OnExtractResource() {
string dataPath = Util.DataPath; //数据目录
string resPath = Util.AppContentPath(); //游戏包资源目录
string infile = resPath + "files.txt";
string outfile = dataPath + "files.txt";
string message = "";
if (firstExtractResource)
{
//创建Util.DataPath目录
if (Directory.Exists(dataPath)) Directory.Delete(dataPath, true);
Directory.CreateDirectory(dataPath);
if (File.Exists(outfile)) File.Delete(outfile);
//解包files.txt
message = "正在解包文件:>files.txt";
Debug.Log("正在解包文件:>files.txt");
//facade.SendMessageCommand(NotiConst.EXTRACT_FILE_NAME, message);
if (Application.platform == RuntimePlatform.Android)
{
WWW www = new WWW(infile);
yield return www;
if (www.isDone)
{
File.WriteAllBytes(outfile, www.bytes);
}
yield return 0;
}
else File.Copy(infile, outfile, true);
//yield return new WaitForEndOfFrame();
}
List willExtractFileName = new List();
//释放文件到数据目录,过滤要解包的文件
string[] files = File.ReadAllLines(outfile);
foreach (var file in files)
{
string[] fs = file.Split('|');
infile = resPath + fs[0];
outfile = dataPath + fs[0];
//start是主界面的包,需要自行修改
bool a = fs[0].StartsWith("lua/") || fs[0].StartsWith("StreamingAssets") ||fs[0].StartsWith("start");
if (firstExtractResource && !a) continue;
if (!firstExtractResource && a) continue;
//message = "正在解包文件:>" + fs[0];
//Debug.Log("正在解包文件:>" + infile);
//facade.SendMessageCommand(NotiConst.EXTRACT_FILE_NAME, fs[0]);
string dir = Path.GetDirectoryName(outfile);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
willExtractFileName.Add(fs[0]);
}
//第二次解包才显示信息
if (!firstExtractResource && (willExtractFileName.Count > 0))
facade.SendMessageCommand(NotiConst.EXTRACT_ALL_COUNT, willExtractFileName.Count);
for (int i = 0; i < willExtractFileName.Count; i++)
{
Debug.Log("正在解包:" + willExtractFileName[i]);
string from = resPath + willExtractFileName[i];
string to = dataPath + willExtractFileName[i];
if (Application.platform == RuntimePlatform.Android)
{
if (!firstExtractResource) facade.SendMessageCommand(NotiConst.EXTRACT_FILE_NAME, willExtractFileName[i]);
WWW www = new WWW(from);
yield return www;
if (www.isDone)
{
File.WriteAllBytes(to, www.bytes);
if (!firstExtractResource) facade.SendMessageCommand(NotiConst.EXTRACT_FINISH_ONE, 0);
}
yield return 0;
}
else
{
if (File.Exists(to))
{
File.Delete(to);
}
if (!firstExtractResource) facade.SendMessageCommand(NotiConst.EXTRACT_FILE_NAME, willExtractFileName[i]);
File.Copy(from, to, true);
if (!firstExtractResource) facade.SendMessageCommand(NotiConst.EXTRACT_FINISH_ONE, 0);
}
yield return new WaitForEndOfFrame();
}
;
if (firstExtractResource)
{
ResManager.initialize(OnResourceInited);
}
else
{
message = "解包完成!!!";
//facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
//释放完成,开始启动更新资源
StartCoroutine(OnUpdateResource());
}
yield return new WaitForSeconds(0.1f);
message = string.Empty;
}
///
/// 启动更新下载,这里只是个思路演示,此处可启动线程下载更新
///
IEnumerator OnUpdateResource() {
downloadFiles.Clear();
if (!AppConst.UpdateMode) {
//ResManager.initialize(OnResourceInited);
yield break;
}
string dataPath = Util.DataPath; //数据目录
string url = AppConst.WebUrl;
string random = DateTime.Now.ToString("yyyymmddhhmmss");
string listUrl = url + "files.txt?v=" + random;
Debug.LogWarning("LoadUpdate---->>>" + listUrl);
WWW www = new WWW(listUrl); yield return www;
if (www.error != null) {
OnUpdateFailed(string.Empty);
yield break;
}
if (!Directory.Exists(dataPath)) {
Directory.CreateDirectory(dataPath);
}
File.WriteAllBytes(dataPath + "files.txt", www.bytes);
string filesText = www.text;
string[] files = filesText.Split('\n');
List willDownLoadUrl = new List();//from
List willDownLoadFileName = new List();
List willDownLoadDestination = new List();//to
string message = string.Empty;
for (int i = 0; i < files.Length; i++)
{
if (string.IsNullOrEmpty(files[i])) continue;
string[] keyValue = files[i].Split('|');
string f = keyValue[0];
string localfile = (dataPath + f).Trim();
string path = Path.GetDirectoryName(localfile);
if (!Directory.Exists(path)) {
Directory.CreateDirectory(path);
}
string fileUrl = url + keyValue[0] + "?v=" + random;
bool canUpdate = !File.Exists(localfile);
if (!canUpdate) {
string remoteMd5 = keyValue[1].Trim();
string localMd5 = Util.md5file(localfile);
canUpdate = !remoteMd5.Equals(localMd5);
if (canUpdate) File.Delete(localfile);
}
if (canUpdate) { //本地缺少文件
//Debug.Log(fileUrl);
//message = "downloading>>" + fileUrl;
//facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
/*
www = new WWW(fileUrl); yield return www;
if (www.error != null) {
OnUpdateFailed(path); //
yield break;
}
File.WriteAllBytes(localfile, www.bytes);
* */
willDownLoadUrl.Add(fileUrl);//下载地址
willDownLoadFileName.Add(keyValue[0]);
willDownLoadDestination.Add(localfile);//目标文件路径
}
}
if (willDownLoadUrl.Count > 0) facade.SendMessageCommand(NotiConst.UPDATE_ALL_COUNT, willDownLoadUrl.Count);
for (int i = 0; i < willDownLoadUrl.Count; i++)
{
Debug.Log("要下载的文件:" + willDownLoadUrl[i]);
//这里都是资源文件,用线程下载
facade.SendMessageCommand(NotiConst.UPDATE_FILE_NAME, willDownLoadFileName[i]);
BeginDownload(willDownLoadUrl[i], willDownLoadDestination[i]);
//while (!(IsDownOK(willDownLoadDestination[i]))) { yield return new WaitForEndOfFrame(); }
}
yield return new WaitForEndOfFrame();
message = "更新完成!!";
//facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
//ResManager.initialize(OnResourceInited);
}
///
/// 是否下载完成
///
bool IsDownOK(string file) {
return downloadFiles.Contains(file);
}
///
/// 线程下载
///
void BeginDownload(string url, string file) { //线程下载
object[] param = new object[2] {url, file};
ThreadEvent ev = new ThreadEvent();
ev.Key = NotiConst.THREAD_DOWNLOAD;
ev.evParams.AddRange(param);
ThreadManager.AddEvent(ev, OnThreadCompleted); //线程下载
}
///
/// 线程完成
///
///
void OnThreadCompleted(NotiData data) {
switch (data.evName) {
case NotiConst.THREAD_EXTRACT: //解压一个完成
//
break;
case NotiConst.THREAD_DOWNLOAD: //下载一个完成
downloadFiles.Add(data.evParam.ToString());
break;
}
}
void OnUpdateFailed(string file) {
string message = "更新失败!>" + file;
Debug.Log(message);
//facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
}
///
/// 资源初始化结束
///
public void OnResourceInited() {
LuaManager.InitStart();
LuaManager.DoFile("Logic/Game"); //加载游戏
LuaManager.DoFile("Logic/Network"); //加载网络
NetManager.OnInit(); //初始化网络
Util.CallMethod("Game", "OnInitOK"); //初始化完成
initialize = true; //初始化完
//类对象池测试
var classObjPool = ObjPoolManager.CreatePool(OnPoolGetElement, OnPoolPushElement);
//方法1
//objPool.Release(new TestObjectClass("abcd", 100, 200f));
//var testObj1 = objPool.Get();
//方法2
ObjPoolManager.Release(new TestObjectClass("abcd", 100, 200f));
var testObj1 = ObjPoolManager.Get();
Debugger.Log("TestObjectClass--->>>" + testObj1.ToString());
//游戏对象池测试
var prefab = Resources.Load("TestGameObjectPrefab", typeof(GameObject)) as GameObject;
var gameObjPool = ObjPoolManager.CreatePool("TestGameObject", 5, 10, prefab);
var gameObj = Instantiate(prefab) as GameObject;
gameObj.name = "TestGameObject_01";
gameObj.transform.localScale = Vector3.one;
gameObj.transform.localPosition = Vector3.zero;
ObjPoolManager.Release("TestGameObject", gameObj);
var backObj = ObjPoolManager.Get("TestGameObject");
backObj.transform.SetParent(null);
Debug.Log("TestGameObject--->>>" + backObj);
if (hadExtractResource)
{
StartCoroutine(OnUpdateResource());
}
else
{
firstExtractResource = false;//进行二次解包
hadExtractResource = true;
StartCoroutine(OnExtractResource());
}
}
///
/// 当从池子里面获取时
///
///
void OnPoolGetElement(TestObjectClass obj) {
Debug.Log("OnPoolGetElement--->>>" + obj);
}
///
/// 当放回池子里面时
///
///
void OnPoolPushElement(TestObjectClass obj) {
Debug.Log("OnPoolPushElement--->>>" + obj);
}
///
/// 析构函数
///
void OnDestroy() {
if (NetManager != null) {
NetManager.Unload();
}
if (LuaManager != null) {
LuaManager.Close();
}
Debug.Log("~GameManager was destroyed");
}
}
}
3.接着就是把信息显示出来了。
修改AppView.cs
using UnityEngine;
using LuaFramework;
using System.Collections.Generic;
public class AppView : View {
private string message;
///
/// 监听的消息
///
List MessageList {
get {
return new List()
{
NotiConst.EXTRACT_FILE_NAME,
NotiConst.EXTRACT_FINISH_ONE,
NotiConst.EXTRACT_ALL_COUNT,
NotiConst.UPDATE_SPEED,
NotiConst.UPDATE_FILE_NAME,
NotiConst.UPDATE_FINISH_ONE,
NotiConst.UPDATE_ALL_COUNT,
};
}
}
void Awake() {
RemoveMessage(this, MessageList);
RegisterMessage(this, MessageList);
}
///
/// 处理View消息
///
///
public override void OnMessage(IMessage message) {
string name = message.Name;
object body = message.Body;
this.message = message.Name;
switch (name) {
case NotiConst.EXTRACT_FILE_NAME:
extractFileName = body.ToString();
break;
case NotiConst.EXTRACT_FINISH_ONE:
extractNowCount++;
break;
case NotiConst.EXTRACT_ALL_COUNT:
extractAllCount = (int)body;
break;
case NotiConst.UPDATE_SPEED:
updateSpeed = body.ToString();
break;
case NotiConst.UPDATE_FILE_NAME:
updateFileName = body.ToString();
break;
case NotiConst.UPDATE_FINISH_ONE:
updateNowCount++;
break;
case NotiConst.UPDATE_ALL_COUNT:
updateAllCount = (int)body;
break;
}
}
string extractFileName;
int extractNowCount = 0;
int extractAllCount = 0;
string updateFileName;
int updateNowCount = 0;
int updateAllCount = 0;
string updateSpeed;
void OnGUI()
{
if (string.IsNullOrEmpty(message)) return;
if (message.StartsWith("EXTRACT_"))
{
GUILayout.Label("正在解包的文件:" + extractFileName);
GUILayout.Label("当前解包数:" + extractNowCount);
GUILayout.Label("总的解包数:" + extractAllCount);
}
else if (message.StartsWith("UPDATE_"))
{
GUILayout.Label("正在下载的文件:" + updateFileName);
GUILayout.Label("当前下载数:" + updateNowCount);
GUILayout.Label("总的下载数:" + updateAllCount);
GUILayout.Label("下载速度:" + updateSpeed);
}
}
}
4.最后,因为消息类型变了,所以还要修改ThreadManager.cs
using System.Collections;
using System.Threading;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Net;
using System;
using Debug = UnityEngine.Debug;
public class ThreadEvent {
public string Key;
public List