目錄
打包與資源加載框架目錄
正文
下載AB包之前,要檢查該AB包是否下載中斷過(guò),例如用戶殺程序,卡死等情況。
前文有講解過(guò),下載AB包會(huì)先下載到臨時(shí)文件夾,全部下載成功后,全部剪切到persistentDataPath沙盒目錄中。
回顧一下之前的篩選機(jī)制,哪些AB包可以加入下載列表,其中并沒(méi)有臨時(shí)下載目錄的判斷。
該AB包數(shù)據(jù)是否加入列表要經(jīng)過(guò)下面幾個(gè)篩選
判斷persistentDataPath沙盒目錄是否存在該AB包,如果存在證明之前下載過(guò),無(wú)需加入下載列表。
判斷StreamingAsset目錄中是否存在該AB包,如果存在證明打包時(shí)該AB包已經(jīng)在包體里,無(wú)需加入下載列表。
如果該AB包的下載類(lèi)型是游戲內(nèi)下載,或者叫邊玩邊下,那么不需要在游戲啟動(dòng)熱更時(shí)下載,無(wú)需加入下載列表
檢查是否在臨時(shí)下載目錄中是否存在的代碼如下
private IEnumerator CheckTempFileComplete(List<PatchElement> list, bool isPostCheck)
{
PatchEventDispatcher.SendCheckDownloadedFileMd5();
var sw = new Stopwatch();
sw.Start();
var buf = new byte[10240];
this.totalDownloadSizeKB = 0;
this.currentDownloadSizeKB = 0;
this.currentDownloadCount = 0;
using (var md5 = System.Security.Cryptography.MD5.Create())
{
foreach (var ele in list)
{
this.totalDownloadSizeKB += ele.SizeKB;
string savePath = AssetPathHelper.MakeDownloadTempPath(ele.Name);
if (!File.Exists(savePath))
{
//下載后的檢查需要拋出異常,下載前的檢查跳過(guò)不存在文件
if (isPostCheck)
{
PatchHelper.Log(ELogLevel.Error, $"[checking md5] file is not existed: {ele.Name}");
failedOnCheckDownload = true;
yield break;
}
else
{
continue;
}
}
using (var fs = new FileStream(savePath, FileMode.Open, FileAccess.Read))
{
int byteRead;
md5.Initialize();
while ((byteRead = fs.Read(buf, 0, buf.Length)) > 0)
{
md5.TransformBlock(buf, 0, byteRead, null, 0);
if (sw.ElapsedMilliseconds > 250)
{
yield return null;
sw.Restart();
}
}
md5.TransformFinalBlock(buf, 0, 0);
fs.Close();
string localMd5 = BitConverter.ToString(md5.Hash).Replace("-", "");
if (string.Equals(ele.MD5, localMd5, StringComparison.OrdinalIgnoreCase))
{
//MotionLog.Log(ELogLevel.Log, StringFormat.Format("skip download existed file: {0}", savePath));
ele.SkipDownload = true;
this.currentDownloadSizeKB += ele.SizeKB;
this.currentDownloadCount++;
}
else if (isPostCheck)
{
PatchHelper.Log(ELogLevel.Error, $"Web file md5 verification error : {ele.Name}");
PatchHelper.Log(ELogLevel.Error, $"local md5 is : {localMd5}");
PatchHelper.Log(ELogLevel.Error, $"md5 in manifest is : {ele.MD5}");
PatchEventDispatcher.SendWebFileMD5VerifyFailedMsg(ele.Name);
failedOnCheckDownload = true;
File.Delete(savePath);
yield break;
}
}
}
}
}
布爾值isPostCheck的作用是是否是二次檢測(cè),先不管它
按流程來(lái)走
檢查該AB包是否在臨時(shí)文件夾中存在,如果不存在則跳過(guò)
如果已存在,創(chuàng)建該臨時(shí)下載文件的MD5,與下載清單中的MD5做對(duì)比
如果MD5對(duì)比一致,則標(biāo)記該AB包數(shù)據(jù)為SkipDownload,同時(shí)標(biāo)記下載數(shù)據(jù)長(zhǎng)度,供UI顯示
我們項(xiàng)目里目前的代碼被人改了,我也有有點(diǎn)看不懂為何要用 md5.TransformBlock的方式
下面是一套生成MD5碼的代碼,加載文件,MD5CryptoServiceProvider會(huì)根據(jù)加載的stream生成hash,文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-476842.html
readonly MD5CryptoServiceProvider _provider = new MD5CryptoServiceProvider();
public static string StreamMD5()
{
? ? using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
? ? {
? ? byte[] hashBytes = _provider.ComputeHash(stream);
? ? return ToString(hashBytes);
? ? }
}
private static string ToString(byte[] hashBytes)
{
? ? var sb = new StringBuilder();
? ? foreach (var t in hashBytes)
? ? sb.Append(t.ToString("x2"));
? ? return sb.ToString();
}
首先要判斷臨時(shí)下載目錄中是否存在該文件,如果沒(méi)有,我們項(xiàng)目文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-476842.html
private IEnumerator Download()
{
// 計(jì)算下載文件的總大小
totalDownloadCount = _patcher.DownloadList.Count;
if (totalDownloadCount == 0)
{
_patcher.SwitchNext();
yield break;
}
//先檢查一遍temp目錄有沒(méi)有下載完的, 計(jì)算這次實(shí)際需要下載的個(gè)數(shù)和size
yield return CheckTempFileComplete(_patcher.DownloadList, false);
// 開(kāi)始下載列表里的所有資源
PatchHelper.Log(ELogLevel.Log, $"Begine download web files : {totalDownloadCount-currentDownloadCount}");
PatchEventDispatcher.SendPatchStatesChangeMsg(EPatchStates.DownloadWebFiles);
var startTime = Time.realtimeSinceStartup;
var newDownloaded = new List<PatchElement>(_patcher.DownloadList.Count);
foreach (var element in _patcher.DownloadList)
{
if (element.SkipDownload) continue;
newDownloaded.Add(element);
}
if (useMultiRequest)
{
yield return DownloadWithMultiTask(newDownloaded);
}
else
{
yield return DownloadWithSingleTask(newDownloaded);
}
if (failedOnDownload)
{
yield break;
}
MotionLog.Log(ELogLevel.Log, $"<color=#ff0000>Downloading {newDownloaded.Count} files cost {Time.realtimeSinceStartup-startTime} sec.</color>");
//全部下載完成后把這次新下載的文件再校驗(yàn)一遍,如果有文件失敗就退出
yield return CheckTempFileComplete(newDownloaded, true);
if (failedOnCheckDownload)
{
yield break;
}
if (_patcher.MiniAndroid)
{
var fileCount = _patcher.DownloadList[0].Version; // tricky storing filecount in field [version]
var zipFileName = _patcher.DownloadList[0].Name;
yield return DecompressInitPack(zipFileName, fileCount);
}
else
{
yield return DeployDownloadFiles();
}
// 最后清空下載列表
_patcher.DownloadList.Clear();
_patcher.SwitchNext();
}
到了這里,關(guān)于[游戲開(kāi)發(fā)][Unity]Assetbundle加載篇(4)檢查斷點(diǎn)續(xù)傳以及開(kāi)始下載AB包的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!