Unity3D 更新文件下载器
使用说明:
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<PatchFileDownloader>();
if (null == downloader)
{
downloader = gameObject.AddComponent<PatchFileDownloader>();
}
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 PatchFileDownloader : 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 ( == val.Length)
{
PartialUrl = val[];
RelativePath = val[];
}
else if ( == val.Length)
{
PartialUrl = val[];
RelativePath = val[];
}
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 = ; //当前已下载的bundle个数
private int mBundleCount = ; //开始下载
public void Download(string url,string dir)
{
mBundleCount = ;
mTotalBundleCount = ;
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 = ; i < list.Count; i++)
{
var info = new PatchFileInfo(list[i]); if (!CheckNeedDownload(info))
{
continue;
} fileList.Add(info);
} mTotalBundleCount = fileList.Count; //开始下载所有文件
for (int i = ; 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 = CreateDirectoryRecursive(filePath) + "/" + fileName; FileStream fs1 = File.Open(writePath, FileMode.OpenOrCreate);
fs1.Write(www.bytes, , www.bytesDownloaded);
fs1.Close(); //Debug.Log("download " + writePath);
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 CreateDirectoryRecursive(string relativePath)
{
var list = relativePath.Split('/');
var temp = Application.temporaryCachePath;
for (int i=;i<list.Length-;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 fallPath = Path.Combine(Application.temporaryCachePath, relativePath);
if (string.IsNullOrEmpty(relativePath))
{
Caching.CleanCache();
return;
} var dirs = Directory.GetDirectories(fallPath);
var files = Directory.GetFiles(fallPath); foreach (var file in files)
{
File.Delete(file);
} foreach (var dir in dirs)
{
Directory.Delete(dir, true);
} Debug.Log("CleaDirectory " + fallPath);
} //检查是否已经下载完毕
IEnumerator CheckLoadFinish()
{
while (mBundleCount < mTotalBundleCount)
{
yield return null;
} if (null != OnDownLoadOver)
{
try
{
OnDownLoadOver(true);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
}
Unity3D 更新文件下载器的更多相关文章
- Atitit 热更新资源管理器 自动更新管理器 功能设计
Atitit 热更新资源管理器 自动更新管理器 功能设计 · 多线程并行下载支持 · 两层进度统计信息:文件级以及字节级 · Zip压缩文件支持 · 断点续传 · 详细的错误报告 · 文件下载失败重试 ...
- tcp案例之文件下载器
文件下载器客户端 import socket def main(): # 1.创建一个tcp socket tcp_client_socket=socket.socket(socket.AF_INET ...
- python实现tcp文件下载器
服务器端代码 import socket import os import threading # 处理客户端请求下载文件的操作(从主线程提出来的代码) def deal_client_request ...
- 使用网络TCP搭建一个简单文件下载器
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 目录 一丶项目介绍 二丶服务器Server 三丶测试TCP server服务器 四丶客户端Client 五丶测试客户端向服务器下载 ...
- {每日一题}:tcp协议实现简单的文件下载器(单任务版)
文件下载器客户端 这个版本的只是为了方便回顾一下TCP客服端,服务端的创建流程,缺点就是 服务器一次只能让一个人访问下载,过两个写个使用面向对象写一个多线程版的强化一下. from socket i ...
- QT--HTTP文件下载器
QT--HTTP文件下载器 1.pro文件添加 QT += core gui network 2.头文件 #include <QNetworkAccessManager> #i ...
- Unity3D --对撞机/碰撞器 介绍
碰撞器一般都用作触发器而用,刚体一般用作真实碰撞. 静态对撞机:一个对象有对撞机组件,没有刚体组件. 这种情况在场景中的静态物体应用较多,比如墙体,房屋等静止不动的物体. 物理引擎假设静态对撞机是不会 ...
- warensoft unity3d 更新说明
warensoft unity3d 组件的Alpha版本已经发布了将近一年,很多网友发送了改进的Email,感谢大家的支持. Warensoft Unity3D组件将继续更新,将改进的功能如下: 1. ...
- Unity3D合并着色器
unity 3d倒每次模型更多的是一种着色器.我可以拥有这些车型共享的地图想分享一个着色器.所以每次删除,然后附加,很麻烦.如何才能合并这些着色器? 采纳TexturePacking对 1.遍历gam ...
随机推荐
- matlab常用的字符串操作函数之一
1,strcat和strvcat strcat:依次横向连接字符串: strvcat:依次纵向连接字符串: 实例1: >>a1='sophia '; >>a2='is a '; ...
- tensorflow学习笔记三:实例数据下载与读取
一.mnist数据 深度学习的入门实例,一般就是mnist手写数字分类识别,因此我们应该先下载这个数据集. tensorflow提供一个input_data.py文件,专门用于下载mnist数据,我们 ...
- FineUI(专业版)v2.6.0即将支持的两个新特性!
特性1:以一挡三,将 160 行代码缩减为 60 行的技巧! 为了更新单元格的编辑值,我们需要下面三个函数同时上阵: GetModifiedDict:修改的单元格值 GetDeletedList:删除 ...
- Prototype原型(创建型模式)
依赖关系的倒置:抽象不应该依赖于实现的细节,实现细节应该依赖于抽象. 原型模式的定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.prototype模式允许一个对象再创建另外一个可 ...
- ModernUI教程:创建自定义主题
Modern UI WPF包括两个内置主题(dark与light).在1.0.3版本,您可以构建自定义的主题.Modern UI应用程序通常有在全局资源字典App.xaml中有如下定义 ...
- Ubuntu 14 設定 遠端連線,讓別台電腦可以連線進來
Ubuntu 14 需 disable 加密,方可 遠端連線 此台電腦 xxx@xxx-ThinkPad-T460p:~$ gsettings set org.gnome.Vino require-e ...
- 使用css3 实现太阳升起落下效果
<!DOCTYPE html><html style="overflow: hidden"><head> <meta http-equiv ...
- 在eclipse中部署jsp项目
昨天在做实验的时候发现图片的路径不对,怎么改都不对,后来想到在浏览器中输入localhost:8080是tomcat服务器的路径,没找到资源是不是就是项没有部署到tomcat中,去tomcat的web ...
- Sikuli图形脚本测试工具安装及介绍(适合小白的测试神器)
sikuli简单安装以及介绍附图: 一.简单介绍 SikuliX官方网站:https://launchpad.net/sikuli/(官方的最新版本是SikuliX1.1.0更新于2015-10-06 ...
- 快速上手php:使用PhpStrom调试php
闲话 使用phpStrom的时候居然不打印到控制台,要打印测试的话就要输出到页面,目前我还不知道有什么好办法像jsp一样输出到页面的同时也打印到控制台.这种做法还是比较烦的,特别出问题需要调试的时候. ...