Unity3d StreamingAssets資源復制到沙盒(一)
由於項目已實現熱更新,所以資源優先由沙盒讀取,或完全直接從沙盒讀取。為了防止在更新大版本時使用到舊項目的資源,所以需要對沙盒中舊的資源進行覆蓋。
暫時實現了以下兩種copy方案。
MD5文件格式與生成:
方法一:將本地資源一次性全部copy到沙盒,僅在首次安裝或覆蓋安裝時對比oldfiles進行篩選覆蓋
缺點:很慢。 30m資源耗時近20s,可優化:文件壓縮後copy過去再解壓。該方案暫時不用,僅做參考
private string oldfilesName = "oldfiles.txt";
private string filesName = "files.txt";
IEnumerator CopyFolder()
{
List<FileInfo> localInfos = new List<FileInfo>();
List<FileInfo> shaheInfos = new List<FileInfo>();
List<FileInfo> copyInfos = new List<FileInfo>();
//本地oldfiles
string src = getStreamingPath_for_www() + oldfilesName;
WWW www = new WWW(src);
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log("www.error:" + www.error);
}
else
{
StringReader reader = new StringReader(www.text);
string line;
while ((line = reader.ReadLine()) != null)
{
string[] temp = line.Split(‘|‘);
string fileName = temp[0];
string md5 = temp[1];
int length = int.Parse(temp[2]);
FileInfo info;
info.fileName = fileName;
info.md5 = md5;
info.length = length;
localInfos.Add(info);
}
reader.Dispose();
reader.Close();
}
www.Dispose();
if (localInfos.Count > 0)
{
//沙盒oldfiles
string des = Application.persistentDataPath + "/" + oldfilesName;
if (File.Exists(des))
{
StreamReader reader = File.OpenText(des);
string line;
while ((line = reader.ReadLine()) != null)
{
string[] temp = line.Split(‘|‘);
string fileName = temp[0];
string md5 = temp[1];
int length = int.Parse(temp[2]);
FileInfo info;
info.fileName = fileName;
info.md5 = md5;
info.length = length;
shaheInfos.Add(info);
}
reader.Dispose();
reader.Close();
}
//需要更新oldfiles
copyInfos = CompareFileInfo(localInfos, shaheInfos);
foreach (var item in copyInfos)
{
//string mfileName = item.fileName.Replace("\\","/");
string _src = getStreamingPath_for_www() + item.fileName;
string fileName = item.fileName.Substring(item.fileName.LastIndexOf(‘/‘) + 1);
string _des = Application.persistentDataPath + "/" + fileName;
//Debug.Log("des:" + _des);
//Debug.Log("src:" + _src);
WWW _www = new WWW(_src);
yield return _www;
if (!string.IsNullOrEmpty(_www.error))
{
Debug.Log("_www.error:" + _www.error);
}
else
{
FileStream stream = new FileStream(_des, FileMode.Create);
stream.Write(_www.bytes, 0, _www.bytes.Length);
stream.Flush();
stream.Close();
}
_www.Dispose();
}
if (copyInfos.Count > 0)
{
//copy oldfiles
StartCoroutine(copy(oldfilesName));
//刪除 file 和 version
//刪除這兩個文件是copy完之後讓遊戲重新進行一次熱更新,以保證沙盒資 源與資源服資源保持一致(也是避免新資源被copy而報錯)
string filepath = Application.persistentDataPath + "/files.txt";
string versionpath = Application.persistentDataPath + "/Version";
if (File.Exists(filepath))
{
File.Delete(filepath);
}
if (File.Exists(versionpath))
{
File.Delete(versionpath);
}
}
Debug.logger.Log("文件復制完成:共" + copyInfos.Count + "個文件");
}
else
{
Debug.logger.Log("本地無文件:" + copyInfos.Count + "個文件");
}
StartCoroutine(compareVersion());
}
/// <summary>
/// 將streaming path 下的文件copy到對應用
///
IEnumerator copy(string fileName)
{
string src = getStreamingPath_for_www() + fileName;
string des = Application.persistentDataPath + "/" + fileName;
//Debug.Log("des:" + des);
//Debug.Log("src:" + src);
WWW www = new WWW(src);
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log("www.error:" + www.error);
}
else
{
if (File.Exists(des))
{
File.Delete(des);
}
FileStream fsDes = File.Create(des);
fsDes.Write(www.bytes, 0, www.bytes.Length);
fsDes.Flush();
fsDes.Close();
}
www.Dispose();
}
//比較md5
List<FileInfo> CompareFileInfo(List<FileInfo> localInfos, List<FileInfo> shaheInfos)
{
List<FileInfo> downloadList = new List<FileInfo>();
for (int i = 0; i < localInfos.Count; i++)
{
FileInfo info = localInfos[i];
bool flag = NeedCopy(info.fileName, info.md5, shaheInfos);
if (flag)
{
downloadList.Add(info);
}
}
return downloadList;
}
//true 需要下載,false 不用下載
bool NeedCopy(string fileName, string md5, List<FileInfo> shaheInfos)
{
for (int i = 0; i < shaheInfos.Count; i++)
{
if (shaheInfos[i].fileName == fileName)
{
if (shaheInfos[i].md5 == md5)
{
return false;
}
else
{
return true;
}
}
}
return true;
}
string getStreamingPath_for_www()
{
string pre = "file://";
#if UNITY_EDITOR
pre = "file://";
#elif UNITY_ANDROID
pre = "";
#elif UNITY_IPHONE
pre = "file://";
#endif
string path = pre + Application.streamingAssetsPath + "/";
return path;
}
string getPersistentPath_for_www()
{
string pre = "file://";
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
pre = "file:///";
#elif UNITY_ANDROID
pre = "file://";
#elif UNITY_IPHONE
pre = "file://";
#endif
string path = pre + Application.persistentDataPath + "/";
return path;
}
#endregion
方法二、僅copy覆蓋沙盒中存在的舊資源
本文出自 “wo愛錢” 博客,請務必保留此出處http://mozhenrui.blog.51cto.com/11845221/1936625
Unity3d StreamingAssets資源復制到沙盒(一)