Unity3D 更新远程文件下载器

转载 原文地址 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);
            }
        }
 }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值