diff --git a/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdateManifestOperation.cs b/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdateManifestOperation.cs
index d0b6f44..8bd39eb 100644
--- a/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdateManifestOperation.cs
+++ b/Assets/YooAsset/Runtime/PatchSystem/Operations/UpdateManifestOperation.cs
@@ -69,6 +69,7 @@ namespace YooAsset
private ESteps _steps = ESteps.None;
private UnityWebDataRequester _downloader1;
private UnityWebDataRequester _downloader2;
+ private VerifyManager _verifyManager = new VerifyManager();
private float _verifyTime;
internal HostPlayModeUpdateManifestOperation(HostPlayModeImpl impl, int resourceVersion, int timeout)
@@ -171,20 +172,20 @@ namespace YooAsset
if (_steps == ESteps.InitVerifyingCache)
{
- InitVerifyingCache();
+ _verifyManager.InitVerifyingCache(_impl.AppPatchManifest, _impl.LocalPatchManifest, false);
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
_steps = ESteps.UpdateVerifyingCache;
}
if (_steps == ESteps.UpdateVerifyingCache)
{
- Progress = GetVerifyProgress();
- if (UpdateVerifyingCache())
+ Progress = _verifyManager.GetVerifyProgress();
+ if (_verifyManager.UpdateVerifyingCache())
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
- YooLogger.Log($"Verify result : Success {_verifySuccessCount}, Fail {_verifyFailCount}, Elapsed time {costTime} seconds");
+ YooLogger.Log($"Verify result : Success {_verifyManager.VerifySuccessCount}, Fail {_verifyManager.VerifyFailCount}, Elapsed time {costTime} seconds");
}
}
}
@@ -248,8 +249,107 @@ namespace YooAsset
else
return string.Empty;
}
+ }
- #region 多线程相关
+ ///
+ /// 网络模式的更新清单操作(弱联网)
+ ///
+ internal sealed class HostPlayModeWeaklyUpdateManifestOperation : UpdateManifestOperation
+ {
+ private enum ESteps
+ {
+ None,
+ LoadSandboxManifestHash,
+ InitVerifyingCache,
+ UpdateVerifyingCache,
+ Done,
+ }
+
+ private readonly HostPlayModeImpl _impl;
+ private readonly int _resourceVersion;
+ private ESteps _steps = ESteps.None;
+ private VerifyManager _verifyManager = new VerifyManager();
+ private float _verifyTime;
+
+ internal HostPlayModeWeaklyUpdateManifestOperation(HostPlayModeImpl impl, int resourceVersion)
+ {
+ _impl = impl;
+ _resourceVersion = resourceVersion;
+ }
+ internal override void Start()
+ {
+ _steps = ESteps.LoadSandboxManifestHash;
+ }
+ internal override void Update()
+ {
+ if (_steps == ESteps.None || _steps == ESteps.Done)
+ return;
+
+ if (_steps == ESteps.LoadSandboxManifestHash)
+ {
+ LoadSandboxPatchManifest(_resourceVersion);
+ _steps = ESteps.InitVerifyingCache;
+ }
+
+ if (_steps == ESteps.InitVerifyingCache)
+ {
+ if (_verifyManager.InitVerifyingCache(_impl.AppPatchManifest, _impl.LocalPatchManifest, true))
+ {
+ _verifyTime = UnityEngine.Time.realtimeSinceStartup;
+ _steps = ESteps.UpdateVerifyingCache;
+ }
+ else
+ {
+ _steps = ESteps.Done;
+ Status = EOperationStatus.Failed;
+ Error = $"The resource version {_resourceVersion} content is not complete !";
+ }
+ }
+
+ if (_steps == ESteps.UpdateVerifyingCache)
+ {
+ Progress = _verifyManager.GetVerifyProgress();
+ if (_verifyManager.UpdateVerifyingCache())
+ {
+ float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
+ YooLogger.Log($"Verify result : Success {_verifyManager.VerifySuccessCount}, Fail {_verifyManager.VerifyFailCount}, Elapsed time {costTime} seconds");
+ if (_verifyManager.VerifyFailCount > 0)
+ {
+ _steps = ESteps.Done;
+ Status = EOperationStatus.Failed;
+ Error = $"The resource version {_resourceVersion} content has verify failed file !";
+ }
+ else
+ {
+ _steps = ESteps.Done;
+ Status = EOperationStatus.Succeed;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 加载沙盒内的补丁清单
+ /// 注意:在加载本地补丁清单之前,未验证过文件的哈希值
+ ///
+ private void LoadSandboxPatchManifest(int updateResourceVersion)
+ {
+ string filePath = PathHelper.MakePersistentLoadPath(YooAssetSettingsData.GetPatchManifestFileName(updateResourceVersion));
+ if (File.Exists(filePath))
+ {
+ YooLogger.Log("Load sandbox patch manifest file.");
+ string jsonData = File.ReadAllText(filePath);
+ var sandboxPatchManifest = PatchManifest.Deserialize(jsonData);
+ _impl.SetLocalPatchManifest(sandboxPatchManifest);
+ }
+ }
+ }
+
+ ///
+ /// 本地缓存文件验证管理器
+ ///
+ internal class VerifyManager
+ {
private class ThreadInfo
{
public bool Result = false;
@@ -267,13 +367,14 @@ namespace YooAsset
private readonly ThreadSyncContext _syncContext = new ThreadSyncContext();
private int _verifyMaxNum = 32;
private int _verifyTotalCount = 0;
- private int _verifySuccessCount = 0;
- private int _verifyFailCount = 0;
- private void InitVerifyingCache()
+ 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 _impl.LocalPatchManifest.BundleList)
+ foreach (var patchBundle in localPatchManifest.BundleList)
{
// 忽略缓存文件
if (DownloadSystem.ContainsVerifyFile(patchBundle.Hash))
@@ -281,18 +382,27 @@ namespace YooAsset
// 忽略APP资源
// 注意:如果是APP资源并且哈希值相同,则不需要下载
- if (_impl.AppPatchManifest.Bundles.TryGetValue(patchBundle.BundleName, out PatchBundle appPatchBundle))
+ if (appPatchManifest.Bundles.TryGetValue(patchBundle.BundleName, out PatchBundle appPatchBundle))
{
if (appPatchBundle.IsBuildin && appPatchBundle.Hash == patchBundle.Hash)
continue;
}
- // 查看文件是否存在
- string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.Hash);
- if (File.Exists(filePath) == false)
- continue;
-
- _waitingList.Add(patchBundle);
+ // 注意:在弱联网模式下,我们需要验证指定资源版本的所有资源完整性
+ if (weaklyUpdate)
+ {
+ string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.Hash);
+ if (File.Exists(filePath))
+ _waitingList.Add(patchBundle);
+ else
+ return false;
+ }
+ else
+ {
+ string filePath = SandboxHelper.MakeCacheFilePath(patchBundle.Hash);
+ if (File.Exists(filePath))
+ _waitingList.Add(patchBundle);
+ }
}
// 设置同时验证的最大数
@@ -300,8 +410,9 @@ namespace YooAsset
YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
_verifyMaxNum = Math.Min(workerThreads, ioThreads);
_verifyTotalCount = _waitingList.Count;
+ return true;
}
- private bool UpdateVerifyingCache()
+ public bool UpdateVerifyingCache()
{
_syncContext.Update();
@@ -331,6 +442,13 @@ namespace YooAsset
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.Hash);
@@ -348,24 +466,17 @@ namespace YooAsset
ThreadInfo info = (ThreadInfo)obj;
if (info.Result)
{
- _verifySuccessCount++;
+ VerifySuccessCount++;
DownloadSystem.CacheVerifyFile(info.Bundle.Hash, info.Bundle.BundleName);
}
else
{
- _verifyFailCount++;
+ VerifyFailCount++;
YooLogger.Warning($"Failed to verify file : {info.FilePath}");
if (File.Exists(info.FilePath))
File.Delete(info.FilePath);
}
_verifyingList.Remove(info.Bundle);
}
- private float GetVerifyProgress()
- {
- if (_verifyTotalCount == 0)
- return 1f;
- return (float)(_verifySuccessCount + _verifyFailCount) / _verifyTotalCount;
- }
- #endregion
}
}
\ No newline at end of file
diff --git a/Assets/YooAsset/Runtime/PatchSystem/PlayMode/HostPlayModeImpl.cs b/Assets/YooAsset/Runtime/PatchSystem/PlayMode/HostPlayModeImpl.cs
index b9fdc84..2fbe32e 100644
--- a/Assets/YooAsset/Runtime/PatchSystem/PlayMode/HostPlayModeImpl.cs
+++ b/Assets/YooAsset/Runtime/PatchSystem/PlayMode/HostPlayModeImpl.cs
@@ -56,6 +56,16 @@ namespace YooAsset
OperationSystem.StartOperaiton(operation);
return operation;
}
+
+ ///
+ /// 异步更新补丁清单(弱联网)
+ ///
+ public UpdateManifestOperation WeaklyUpdatePatchManifestAsync(int resourceVersion)
+ {
+ var operation = new HostPlayModeWeaklyUpdateManifestOperation(this, resourceVersion);
+ OperationSystem.StartOperaiton(operation);
+ return operation;
+ }
///
/// 异步更新资源包裹
diff --git a/Assets/YooAsset/Runtime/YooAssets.cs b/Assets/YooAsset/Runtime/YooAssets.cs
index 4808580..8b2f551 100644
--- a/Assets/YooAsset/Runtime/YooAssets.cs
+++ b/Assets/YooAsset/Runtime/YooAssets.cs
@@ -307,6 +307,36 @@ namespace YooAsset
}
}
+ ///
+ /// 弱联网情况下加载补丁清单
+ /// 注意:当指定版本内容验证失败后会返回失败。
+ ///
+ /// 指定的资源版本
+ public static UpdateManifestOperation WeaklyUpdateManifestAsync(int resourceVersion)
+ {
+ DebugCheckInitialize();
+ if (_playMode == EPlayMode.EditorSimulateMode)
+ {
+ var operation = new EditorPlayModeUpdateManifestOperation();
+ OperationSystem.StartOperaiton(operation);
+ return operation;
+ }
+ else if (_playMode == EPlayMode.OfflinePlayMode)
+ {
+ var operation = new OfflinePlayModeUpdateManifestOperation();
+ OperationSystem.StartOperaiton(operation);
+ return operation;
+ }
+ else if (_playMode == EPlayMode.HostPlayMode)
+ {
+ return _hostPlayModeImpl.WeaklyUpdatePatchManifestAsync(resourceVersion);
+ }
+ else
+ {
+ throw new NotImplementedException();
+ }
+ }
+
///
/// 开启一个异步操作
///