1. 程式人生 > >Unity3d StreamingAssets資源復制到沙盒(一)

Unity3d StreamingAssets資源復制到沙盒(一)

資源copy 沙盒

由於項目已實現熱更新,所以資源優先由沙盒讀取,或完全直接從沙盒讀取。為了防止在更新大版本時使用到舊項目的資源,所以需要對沙盒中舊的資源進行覆蓋。

暫時實現了以下兩種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資源復制到沙盒(一)