diff --git a/Assets/YooAsset/Runtime/DownloadSystem/PatchCacheVerifier.cs b/Assets/YooAsset/Runtime/DownloadSystem/PatchCacheVerifier.cs
new file mode 100644
index 0000000..5144acd
--- /dev/null
+++ b/Assets/YooAsset/Runtime/DownloadSystem/PatchCacheVerifier.cs
@@ -0,0 +1,257 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+
+namespace YooAsset
+{
+ ///
+ /// 本地缓存文件验证器
+ ///
+ internal abstract class PatchCacheVerifier
+ {
+ public abstract bool InitVerifier(PatchManifest appPatchManifest, PatchManifest localPatchManifest, bool weaklyUpdate);
+ public abstract bool UpdateVerifier();
+ public abstract float GetVerifierProgress();
+
+ public int VerifySuccessCount { protected set; get; } = 0;
+ public int VerifyFailCount { protected set; get; } = 0;
+ }
+
+ ///
+ /// 本地缓存文件验证器(线程版)
+ ///
+ internal class PatchCacheVerifierWithThread : PatchCacheVerifier
+ {
+ private class ThreadInfo
+ {
+ public bool Result = false;
+ public string FilePath { private set; get; }
+ public PatchBundle Bundle { private set; get; }
+ public ThreadInfo(string filePath, PatchBundle bundle)
+ {
+ FilePath = filePath;
+ Bundle = bundle;
+ }
+ }
+
+ private readonly ThreadSyncContext _syncContext = new ThreadSyncContext();
+ private readonly List _waitingList = new List(1000);
+ private readonly List _verifyingList = new List(100);
+ private int _verifyMaxNum;
+ private int _verifyTotalCount;
+
+ public override bool InitVerifier(PatchManifest appPatchManifest, PatchManifest localPatchManifest, bool weaklyUpdate)
+ {
+ // 遍历所有文件然后验证并缓存合法文件
+ foreach (var patchBundle in localPatchManifest.BundleList)
+ {
+ // 忽略缓存文件
+ if (DownloadSystem.ContainsVerifyFile(patchBundle.FileHash))
+ continue;
+
+ // 忽略APP资源
+ // 注意:如果是APP资源并且哈希值相同,则不需要下载
+ if (appPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
+ {
+ if (appPatchBundle.IsBuildin && appPatchBundle.FileHash == patchBundle.FileHash)
+ continue;
+ }
+
+ // 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性
+ if (weaklyUpdate)
+ {
+ string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
+ if (File.Exists(filePath))
+ _waitingList.Add(patchBundle);
+ else
+ return false;
+ }
+ else
+ {
+ string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
+ if (File.Exists(filePath))
+ _waitingList.Add(patchBundle);
+ }
+ }
+
+ // 设置同时验证的最大数
+ ThreadPool.GetMaxThreads(out int workerThreads, out int ioThreads);
+ YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
+ _verifyMaxNum = Math.Min(workerThreads, ioThreads);
+ _verifyTotalCount = _waitingList.Count;
+ if (_verifyMaxNum < 1)
+ _verifyMaxNum = 1;
+ return true;
+ }
+ public override bool UpdateVerifier()
+ {
+ _syncContext.Update();
+
+ if (_waitingList.Count == 0 && _verifyingList.Count == 0)
+ return true;
+
+ if (_verifyingList.Count >= _verifyMaxNum)
+ return false;
+
+ for (int i = _waitingList.Count - 1; i >= 0; i--)
+ {
+ if (_verifyingList.Count >= _verifyMaxNum)
+ break;
+
+ var patchBundle = _waitingList[i];
+ if (VerifyFile(patchBundle))
+ {
+ _waitingList.RemoveAt(i);
+ _verifyingList.Add(patchBundle);
+ }
+ else
+ {
+ YooLogger.Warning("The thread pool is failed queued.");
+ break;
+ }
+ }
+
+ return false;
+ }
+ public override float GetVerifierProgress()
+ {
+ if (_verifyTotalCount == 0)
+ return 1f;
+ return (float)(VerifySuccessCount + VerifyFailCount) / _verifyTotalCount;
+ }
+
+ private bool VerifyFile(PatchBundle patchBundle)
+ {
+ string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
+ ThreadInfo info = new ThreadInfo(filePath, patchBundle);
+ return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), info);
+ }
+ private void VerifyInThread(object infoObj)
+ {
+ ThreadInfo info = (ThreadInfo)infoObj;
+ info.Result = DownloadSystem.CheckContentIntegrity(info.FilePath, info.Bundle.FileSize, info.Bundle.FileCRC);
+ _syncContext.Post(VerifyCallback, info);
+ }
+ private void VerifyCallback(object obj)
+ {
+ ThreadInfo info = (ThreadInfo)obj;
+ if (info.Result)
+ {
+ VerifySuccessCount++;
+ DownloadSystem.CacheVerifyFile(info.Bundle.FileHash, info.Bundle.FileName);
+ }
+ else
+ {
+ VerifyFailCount++;
+
+ // NOTE:不期望删除断点续传的资源文件
+ /*
+ YooLogger.Warning($"Failed to verify file : {info.FilePath}");
+ if (File.Exists(info.FilePath))
+ File.Delete(info.FilePath);
+ */
+ }
+ _verifyingList.Remove(info.Bundle);
+ }
+ }
+
+ ///
+ /// 本地缓存文件验证器(非线程版)
+ ///
+ internal class PatchCacheVerifierWithoutThread : PatchCacheVerifier
+ {
+ private readonly List _waitingList = new List(1000);
+ private readonly List _verifyingList = new List(100);
+ private int _verifyMaxNum;
+ private int _verifyTotalCount;
+
+ public override bool InitVerifier(PatchManifest appPatchManifest, PatchManifest localPatchManifest, bool weaklyUpdate)
+ {
+ // 遍历所有文件然后验证并缓存合法文件
+ foreach (var patchBundle in localPatchManifest.BundleList)
+ {
+ // 忽略缓存文件
+ if (DownloadSystem.ContainsVerifyFile(patchBundle.FileHash))
+ continue;
+
+ // 忽略APP资源
+ // 注意:如果是APP资源并且哈希值相同,则不需要下载
+ if (appPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
+ {
+ if (appPatchBundle.IsBuildin && appPatchBundle.FileHash == patchBundle.FileHash)
+ continue;
+ }
+
+ // 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性
+ if (weaklyUpdate)
+ {
+ string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
+ if (File.Exists(filePath))
+ _waitingList.Add(patchBundle);
+ else
+ return false;
+ }
+ else
+ {
+ string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
+ if (File.Exists(filePath))
+ _waitingList.Add(patchBundle);
+ }
+ }
+
+ // 设置同时验证的最大数
+ _verifyMaxNum = 32;
+ _verifyTotalCount = _waitingList.Count;
+ return true;
+ }
+ public override bool UpdateVerifier()
+ {
+ if (_waitingList.Count == 0 && _verifyingList.Count == 0)
+ return true;
+
+ for (int i = _waitingList.Count - 1; i >= 0; i--)
+ {
+ if (_verifyingList.Count >= _verifyMaxNum)
+ break;
+
+ var patchBundle = _waitingList[i];
+ VerifyFile(patchBundle);
+ _waitingList.RemoveAt(i);
+ _verifyingList.Add(patchBundle);
+ }
+
+ _verifyingList.Clear();
+ return false;
+ }
+ public override float GetVerifierProgress()
+ {
+ if (_verifyTotalCount == 0)
+ return 1f;
+ return (float)(VerifySuccessCount + VerifyFailCount) / _verifyTotalCount;
+ }
+
+ private void VerifyFile(PatchBundle patchBundle)
+ {
+ string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
+ bool result = DownloadSystem.CheckContentIntegrity(filePath, patchBundle.FileSize, patchBundle.FileCRC);
+ if (result)
+ {
+ VerifySuccessCount++;
+ DownloadSystem.CacheVerifyFile(patchBundle.FileHash, patchBundle.FileName);
+ }
+ else
+ {
+ VerifyFailCount++;
+
+ // NOTE:不期望删除断点续传的资源文件
+ /*
+ YooLogger.Warning($"Failed to verify file : {info.FilePath}");
+ if (File.Exists(info.FilePath))
+ File.Delete(info.FilePath);
+ */
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/YooAsset/Runtime/DownloadSystem/PatchCacheVerifier.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/PatchCacheVerifier.cs.meta
new file mode 100644
index 0000000..db73986
--- /dev/null
+++ b/Assets/YooAsset/Runtime/DownloadSystem/PatchCacheVerifier.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 223f217ed81460541b5ea7eb7a7d82a4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdateManifestOperation.cs b/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdateManifestOperation.cs
index 9d5e682..7d9aa76 100644
--- a/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdateManifestOperation.cs
+++ b/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdateManifestOperation.cs
@@ -2,7 +2,6 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
-using System.Threading;
namespace YooAsset
{
@@ -69,7 +68,7 @@ namespace YooAsset
private ESteps _steps = ESteps.None;
private UnityWebDataRequester _downloader1;
private UnityWebDataRequester _downloader2;
- private VerifyManager _verifyManager = new VerifyManager();
+ private PatchCacheVerifier _patchCacheVerifier;
private float _verifyTime;
internal HostPlayModeUpdateManifestOperation(HostPlayModeImpl impl, int resourceVersion, int timeout)
@@ -77,6 +76,12 @@ namespace YooAsset
_impl = impl;
_resourceVersion = resourceVersion;
_timeout = timeout;
+
+#if UNITY_WEBGL
+ _patchCacheVerifier = new PatchCacheVerifierWithoutThread();
+#else
+ _patchCacheVerifier = new PatchCacheVerifierWithThread();
+#endif
}
internal override void Start()
{
@@ -172,20 +177,20 @@ namespace YooAsset
if (_steps == ESteps.InitVerifyingCache)
{
- _verifyManager.InitVerifyingCache(_impl.AppPatchManifest, _impl.LocalPatchManifest, false);
+ _patchCacheVerifier.InitVerifier(_impl.AppPatchManifest, _impl.LocalPatchManifest, false);
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
_steps = ESteps.UpdateVerifyingCache;
}
if (_steps == ESteps.UpdateVerifyingCache)
{
- Progress = _verifyManager.GetVerifyProgress();
- if (_verifyManager.UpdateVerifyingCache())
+ Progress = _patchCacheVerifier.GetVerifierProgress();
+ if (_patchCacheVerifier.UpdateVerifier())
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
- YooLogger.Log($"Verify result : Success {_verifyManager.VerifySuccessCount}, Fail {_verifyManager.VerifyFailCount}, Elapsed time {costTime} seconds");
+ YooLogger.Log($"Verify result : Success {_patchCacheVerifier.VerifySuccessCount}, Fail {_patchCacheVerifier.VerifyFailCount}, Elapsed time {costTime} seconds");
}
}
}
@@ -268,13 +273,19 @@ namespace YooAsset
private readonly HostPlayModeImpl _impl;
private readonly int _resourceVersion;
private ESteps _steps = ESteps.None;
- private VerifyManager _verifyManager = new VerifyManager();
+ private PatchCacheVerifier _patchCacheVerifier;
private float _verifyTime;
internal HostPlayModeWeaklyUpdateManifestOperation(HostPlayModeImpl impl, int resourceVersion)
{
_impl = impl;
_resourceVersion = resourceVersion;
+
+#if UNITY_WEBGL
+ _patchCacheVerifier = new PatchCacheVerifierWithoutThread();
+#else
+ _patchCacheVerifier = new PatchCacheVerifierWithThread();
+#endif
}
internal override void Start()
{
@@ -293,7 +304,7 @@ namespace YooAsset
if (_steps == ESteps.InitVerifyingCache)
{
- if (_verifyManager.InitVerifyingCache(_impl.AppPatchManifest, _impl.LocalPatchManifest, true))
+ if (_patchCacheVerifier.InitVerifier(_impl.AppPatchManifest, _impl.LocalPatchManifest, true))
{
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
_steps = ESteps.UpdateVerifyingCache;
@@ -308,12 +319,12 @@ namespace YooAsset
if (_steps == ESteps.UpdateVerifyingCache)
{
- Progress = _verifyManager.GetVerifyProgress();
- if (_verifyManager.UpdateVerifyingCache())
+ Progress = _patchCacheVerifier.GetVerifierProgress();
+ if (_patchCacheVerifier.UpdateVerifier())
{
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
- YooLogger.Log($"Verify result : Success {_verifyManager.VerifySuccessCount}, Fail {_verifyManager.VerifyFailCount}, Elapsed time {costTime} seconds");
- if (_verifyManager.VerifyFailCount > 0)
+ YooLogger.Log($"Verify result : Success {_patchCacheVerifier.VerifySuccessCount}, Fail {_patchCacheVerifier.VerifyFailCount}, Elapsed time {costTime} seconds");
+ if (_patchCacheVerifier.VerifyFailCount > 0)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
@@ -344,143 +355,4 @@ namespace YooAsset
}
}
}
-
- ///
- /// 本地缓存文件验证管理器
- ///
- internal class VerifyManager
- {
- private class ThreadInfo
- {
- public bool Result = false;
- public string FilePath { private set; get; }
- public PatchBundle Bundle { private set; get; }
- public ThreadInfo(string filePath, PatchBundle bundle)
- {
- FilePath = filePath;
- Bundle = bundle;
- }
- }
-
- private readonly List _waitingList = new List(1000);
- private readonly List _verifyingList = new List(100);
- private readonly ThreadSyncContext _syncContext = new ThreadSyncContext();
- private int _verifyMaxNum = 32;
- private int _verifyTotalCount = 0;
-
- public int VerifySuccessCount { private set; get; } = 0;
- public int VerifyFailCount { private set; get; } = 0;
-
- public bool InitVerifyingCache(PatchManifest appPatchManifest, PatchManifest localPatchManifest, bool weaklyUpdate)
- {
- // 遍历所有文件然后验证并缓存合法文件
- foreach (var patchBundle in localPatchManifest.BundleList)
- {
- // 忽略缓存文件
- if (DownloadSystem.ContainsVerifyFile(patchBundle.FileHash))
- continue;
-
- // 忽略APP资源
- // 注意:如果是APP资源并且哈希值相同,则不需要下载
- if (appPatchManifest.TryGetPatchBundle(patchBundle.BundleName, out PatchBundle appPatchBundle))
- {
- if (appPatchBundle.IsBuildin && appPatchBundle.FileHash == patchBundle.FileHash)
- continue;
- }
-
- // 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性
- if (weaklyUpdate)
- {
- string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
- if (File.Exists(filePath))
- _waitingList.Add(patchBundle);
- else
- return false;
- }
- else
- {
- string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
- if (File.Exists(filePath))
- _waitingList.Add(patchBundle);
- }
- }
-
- // 设置同时验证的最大数
- ThreadPool.GetMaxThreads(out int workerThreads, out int ioThreads);
- YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
- _verifyMaxNum = Math.Min(workerThreads, ioThreads);
- _verifyTotalCount = _waitingList.Count;
- return true;
- }
- public bool UpdateVerifyingCache()
- {
- _syncContext.Update();
-
- if (_waitingList.Count == 0 && _verifyingList.Count == 0)
- return true;
-
- if (_verifyingList.Count >= _verifyMaxNum)
- return false;
-
- for (int i = _waitingList.Count - 1; i >= 0; i--)
- {
- if (_verifyingList.Count >= _verifyMaxNum)
- break;
-
- var patchBundle = _waitingList[i];
- if (RunThread(patchBundle))
- {
- _waitingList.RemoveAt(i);
- _verifyingList.Add(patchBundle);
- }
- else
- {
- YooLogger.Warning("The thread pool is failed queued.");
- break;
- }
- }
-
- return false;
- }
- public float GetVerifyProgress()
- {
- if (_verifyTotalCount == 0)
- return 1f;
- return (float)(VerifySuccessCount + VerifyFailCount) / _verifyTotalCount;
- }
-
- private bool RunThread(PatchBundle patchBundle)
- {
- string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.FileName);
- ThreadInfo info = new ThreadInfo(filePath, patchBundle);
- return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), info);
- }
- private void VerifyInThread(object infoObj)
- {
- ThreadInfo info = (ThreadInfo)infoObj;
- info.Result = DownloadSystem.CheckContentIntegrity(info.FilePath, info.Bundle.FileSize, info.Bundle.FileCRC);
- _syncContext.Post(VerifyCallback, info);
- }
- private void VerifyCallback(object obj)
- {
- ThreadInfo info = (ThreadInfo)obj;
- if (info.Result)
- {
- VerifySuccessCount++;
- DownloadSystem.CacheVerifyFile(info.Bundle.FileHash, info.Bundle.FileName);
- }
- else
- {
- VerifyFailCount++;
-
- // NOTE:不期望删除断点续传的资源文件
- /*
- YooLogger.Warning($"Failed to verify file : {info.FilePath}");
- if (File.Exists(info.FilePath))
- File.Delete(info.FilePath);
- */
- }
- _verifyingList.Remove(info.Bundle);
- }
- }
}
\ No newline at end of file
diff --git a/Assets/YooAsset/Runtime/YooAssets.cs b/Assets/YooAsset/Runtime/YooAssets.cs
index f374276..6d5c3d1 100644
--- a/Assets/YooAsset/Runtime/YooAssets.cs
+++ b/Assets/YooAsset/Runtime/YooAssets.cs
@@ -100,10 +100,17 @@ namespace YooAsset
///
public bool ClearCacheWhenDirty = false;
+#if UNITY_WEBGL
+ ///
+ /// WEBGL模式不支持多线程下载
+ ///
+ internal int BreakpointResumeFileSize = int.MaxValue;
+#else
///
/// 启用断点续传功能的文件大小
///
public int BreakpointResumeFileSize = int.MaxValue;
+#endif
///
/// 下载文件校验等级
@@ -194,12 +201,8 @@ namespace YooAsset
// 初始化下载系统
if (_playMode == EPlayMode.HostPlayMode)
{
-#if UNITY_WEBGL
- throw new Exception($"{EPlayMode.HostPlayMode} not supports WebGL platform !");
-#else
var hostPlayModeParameters = parameters as HostPlayModeParameters;
DownloadSystem.Initialize(hostPlayModeParameters.BreakpointResumeFileSize, hostPlayModeParameters.VerifyLevel);
-#endif
}
// 初始化资源系统