转载 原文地址 http://gad.qq.com/article/detail/45394
有些游戏项目为了可以减少客户端的大小,会选择从资源服务器加载资源,这有好处也有弊端,就是每此更新都要远程更新文件下载器,具体内容如下。
使用说明:
1、远端更新服务器目录
Package
|----list.txt
|----a.bundle
|----b.bundle
2、list.txt是更新列表文件
格式是
a.bundle|res/a.bundle
b.bundle|res/b.bundle
(a.bundle是要拼的url,res/a.bundle是要被写在cache的路径)
3、使用代码
var downloader = gameObject.GetComponent<PathFileDownloader>();
if (null == downloader)
{
downloader = gameObject.AddComponent<PathFileDownloader>();
}
downloader.OnDownLoading = (n,c,file,url) =>
{
Debug.Log(url);
};
downloader.OnDownLoadOver = (ret) =>
{
Debug.Log("OnDownLoadOver "+ret.ToString());
};
downloader.Download("http://192.168.1.103:3080/Package/", "list.txt");
using System;
using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
//更新文件下载器
public class PathFileDownloader:MonoBehaviour
{
//每个更新文件的描述信息
protected class PatchFileInfo
{
// str 的格式是 url.txt|dir/a.txt url.txt是要拼的url,dir/a.txt是要被写在cache的路径
public PatchFileInfo(string str)
{
Parse(str);
}
//解析
protected virtual void Parse(string str)
{
var val = str.split("|");
if (1==val.Length)
{
PartialUrl = val[0];
RelativePath = val[0];
}
elseif (2 == val.Length)
{
PartialUrl = val[0];
RelativePath = val[1];
}
else
{
Debug.Log("PatchFileInfo parse error");
}
}
//要被拼接的URL
public string PartialUrl{get;private set;};
//文件相对目录
public string RelativePath{get;private set;};
}
public delegate void DelegateLoading(int idx,int total,string bundleName,string path);
public delegate void DelegateLoadOver(bool success);
//正在下载中回调
public DelegateLoading OnDownLoading;
//下载完成回调
public DelegateLoadOver OnDownLoadOver;
//总共要下载的bundle个数
private int mTotalBundleCount = 0;
// 当前已下载的bundle个数
private int mBundleCount = 0;
//开始下载
public void DownLoad(string url,string dir)
{
mTotalBundleCount = 0;
mBundleCount = 0;
StartCoroutine(CoDownLoad(url,dir));
}
//下载Coroutine
private IEnumerator CoDownLoad(string url,string dir)
{
//先拼接URL
string fullUrl = Path.Combine(url,dir);
//获得更新的文件列表
List<string> list = new List<string>();
//先下载文件列表
using(WWW www = new WWW(fullUrl))
{
yield return www;
if(www.error != null)
{
if(null!= OnDownLoadOver)
{
try
{
OnDownLoadOver(false);
}
catch(Exception e)
{
Debug.LogError(e.Message);
}
}
Debugger.LogError(string.Format("Read {0} failed: {1}", fullUrl, www.error));
yield break;
}
ByteReader reader = new ByteReader(www.bytes);
while(reader.canRead)
{
list.Add(reader.ReadLine());
}
if(null != www.assetBundle)
{
www.assetBundle.Unload(true);
}
www.Dispose();
}
//收集所有需要下载的
var fileList = new List<PatchFileInfo>();
for(int i= 0;i < list.Count;i++)
{
var info = new PatchFileInfo(list[i]);
if(!CheckNeedDownLoad(info))
continue;
fileList.Add(info);
}
mTotalBundleCount = fileList.Count;
//开始下载所有文件
for(int i = 0;i<fileList.Count;i++)
{
var info = fileList[I];
var fileUrl = Path.Combine(url,info.PartialUrl);
StartCoroutine(CoDownLoadAndWriteFile(fileUrl,info.RelativePath));
}
//检查是否下载完毕
StartCoroutine(CheckLoadFinish);
//检查是否该下载
protected virtual bool CheckNeedDownload(PatchFileInfo info)
{
return true;
}
//下载并写入文件
private IEnumerator CoDownLoadAndWriteFile(string url,string filePath)
{
var fileName = Path.GetFileName(filePath);
using(WWW www = new WWW(url))
{
yield return www;
}
if(www.error != null)
{
Debugger.LogError(string.Format("Read {0} failed: {1}", url, www.error));
yield break;
}
var writePath = CreateDirectorRecursive(filePath) + "/" + fileName;
FileStream fs1 = File.Open(writePatch,FileMode.OpenOrCreate);
fs1.Write(www.bytes,0,www.bytesDownloaded);
fs1.Close();
if(null != www.assetbundle)
{
www.assetbundle.Unload(true);
}
www.Dispose();
mBundleCount ++;
if(null != OnDownLoading)
{
try
{
OnDownLoading(mBundleCount,mTotalBundleCount,writePath,url);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
}
//递归创建文件夹
public static string CreateDirectorRecursive(string relativePath)
{
var list = relativePath.split("/");
var temp = Application.presistentDataPath;
for(int i = 0;i < list.Length - 1;i++)
{
var dir = list[i];
if(string.IsNullOrEmpty(dir))
{
continue;
}
temp += "/" + dir;
if(!Directory.Exists(temp))
{
Directory.CreateDirectory(temp);
}
return temp;
}
}
//清空某个目录
public static void CleanDirectory(string relativePath)
{
var fullPath = Path.Combine(Application.presistentDataPath,relativePath);
if(string.IsNullOrEmpty(relativePath))
{
Caching.CleanCache();
return;
}
var dirs = Directory.GetDirectories(fullPath);
var files = Directoy.GetFiles(fullPath);
foreach(var file in files)
{
File.Delete(file);
}
foreach(var dir in dirs)
{
Directory.Delete(dir, true);
}
Debug.Log("CleaDirectory " + fallPath);
}
//检查是否已经下载完毕
public IEnumerator CheckFinish()
{
while(mBundleCount < mTotalBundleCount)
{
yield return null;
}
if (null != OnDownLoadOver)
{
try
{
OnDownLoadOver(true);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
}