Merge branch 'tuyoogame:main' into main
commit
a64d485278
|
@ -199,7 +199,7 @@ namespace YooAsset.Editor
|
|||
{
|
||||
if (IsRawAsset)
|
||||
{
|
||||
string mainBundleName = $"{_mainBundleName}.{YooAssetSettingsData.Setting.RawFileVariant}";
|
||||
string mainBundleName = $"{_mainBundleName}.{YooAssetSettingsData.Setting.RawBundleFileVariant}";
|
||||
_mainBundleName = mainBundleName.ToLower();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace YooAsset
|
|||
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
|
||||
{
|
||||
_steps = ESteps.Download;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedDataFilePath;
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ namespace YooAsset
|
|||
if (loadMethod == EBundleLoadMethod.LoadFromMemory || loadMethod == EBundleLoadMethod.LoadFromStream)
|
||||
{
|
||||
_steps = ESteps.Unpack;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedDataFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ namespace YooAsset
|
|||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
_steps = ESteps.LoadFile;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedDataFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -242,14 +242,11 @@ namespace YooAsset
|
|||
// 在AssetBundle文件加载失败的情况下,我们需要重新验证文件的完整性!
|
||||
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
string cacheLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
if (CacheSystem.VerifyBundle(MainBundleInfo.Bundle, EVerifyLevel.High) != EVerifyResult.Succeed)
|
||||
var result = CacheSystem.VerifyingRecordFile(MainBundleInfo.Bundle.PackageName, MainBundleInfo.Bundle.CacheGUID);
|
||||
if (result != EVerifyResult.Succeed)
|
||||
{
|
||||
if (File.Exists(cacheLoadPath))
|
||||
{
|
||||
YooLogger.Error($"Delete the invalid cache file : {cacheLoadPath}");
|
||||
File.Delete(cacheLoadPath);
|
||||
}
|
||||
YooLogger.Error($"Found possibly corrupt file ! {MainBundleInfo.Bundle.CacheGUID}");
|
||||
CacheSystem.DiscardFile(MainBundleInfo.Bundle.PackageName, MainBundleInfo.Bundle.CacheGUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace YooAsset
|
|||
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
|
||||
{
|
||||
_steps = ESteps.Download;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedDataFilePath;
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
|
||||
{
|
||||
|
@ -57,7 +57,7 @@ namespace YooAsset
|
|||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
_steps = ESteps.LoadCacheFile;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedDataFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -147,14 +147,11 @@ namespace YooAsset
|
|||
// 在AssetBundle文件加载失败的情况下,我们需要重新验证文件的完整性!
|
||||
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
string cacheLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
if (CacheSystem.VerifyBundle(MainBundleInfo.Bundle, EVerifyLevel.High) != EVerifyResult.Succeed)
|
||||
var result = CacheSystem.VerifyingRecordFile(MainBundleInfo.Bundle.PackageName, MainBundleInfo.Bundle.CacheGUID);
|
||||
if (result != EVerifyResult.Succeed)
|
||||
{
|
||||
if (File.Exists(cacheLoadPath))
|
||||
{
|
||||
YooLogger.Error($"Delete the invalid cache file : {cacheLoadPath}");
|
||||
File.Delete(cacheLoadPath);
|
||||
}
|
||||
YooLogger.Error($"Found possibly corrupt file ! {MainBundleInfo.Bundle.CacheGUID}");
|
||||
CacheSystem.DiscardFile(MainBundleInfo.Bundle.PackageName, MainBundleInfo.Bundle.CacheGUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,13 +38,13 @@ namespace YooAsset
|
|||
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
|
||||
{
|
||||
_steps = ESteps.Download;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedDataFilePath;
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
|
||||
{
|
||||
#if UNITY_ANDROID || UNITY_WEBGL
|
||||
_steps = ESteps.Unpack;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedDataFilePath;
|
||||
#else
|
||||
_steps = ESteps.CheckFile;
|
||||
FileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
|
||||
|
@ -53,7 +53,7 @@ namespace YooAsset
|
|||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
_steps = ESteps.CheckFile;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedDataFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -229,15 +229,6 @@ namespace YooAsset
|
|||
return _playModeServices.PreDownloadPackageAsync(packageVersion, timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查包裹内容的完整性
|
||||
/// </summary>
|
||||
public CheckPackageContentsOperation CheckPackageContentsAsync(string packageVersion)
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
return _playModeServices.CheckPackageContentsOperation(packageVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理包裹未使用的缓存文件
|
||||
/// </summary>
|
||||
|
@ -731,12 +722,12 @@ namespace YooAsset
|
|||
/// <summary>
|
||||
/// 是否包含资源文件
|
||||
/// </summary>
|
||||
internal bool IsIncludeBundleFile(string fileName)
|
||||
internal bool IsIncludeBundleFile(string cacheGUID)
|
||||
{
|
||||
// NOTE : 编辑器模拟模式下始终返回TRUE
|
||||
if (_playMode == EPlayMode.EditorSimulateMode)
|
||||
return true;
|
||||
return _playModeServices.ActiveManifest.IsIncludeBundleFile(fileName);
|
||||
return _playModeServices.ActiveManifest.IsIncludeBundleFile(cacheGUID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
[Serializable]
|
||||
internal class CacheFileInfo
|
||||
{
|
||||
public string FileCRC;
|
||||
public long FileSize;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a6296859f09655c4191594304ddf378f
|
||||
guid: e4a97c06e069c1146a881fcb359f9b4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -2,19 +2,19 @@
|
|||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal static class CacheSystem
|
||||
{
|
||||
private readonly static Dictionary<string, PatchBundle> _cachedDic = new Dictionary<string, PatchBundle>(1000);
|
||||
private readonly static Dictionary<string, PackageCache> _cachedDic = new Dictionary<string, PackageCache>(1000);
|
||||
|
||||
/// <summary>
|
||||
/// 初始化时的验证级别
|
||||
/// </summary>
|
||||
public static EVerifyLevel InitVerifyLevel { set; get; } = EVerifyLevel.Low;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 清空所有数据
|
||||
/// </summary>
|
||||
|
@ -25,103 +25,119 @@ namespace YooAsset
|
|||
|
||||
/// <summary>
|
||||
/// 查询是否为验证文件
|
||||
/// 注意:被收录的文件完整性是绝对有效的
|
||||
/// </summary>
|
||||
public static bool IsCached(PatchBundle patchBundle)
|
||||
public static bool IsCached(string packageName, string cacheGUID)
|
||||
{
|
||||
string cacheKey = patchBundle.CacheKey;
|
||||
if (_cachedDic.ContainsKey(cacheKey))
|
||||
var cache = GetOrCreateCache(packageName);
|
||||
return cache.IsCached(cacheGUID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 录入验证的文件
|
||||
/// </summary>
|
||||
public static void RecordFile(string packageName, string cacheGUID, PackageCache.RecordWrapper wrapper)
|
||||
{
|
||||
var cache = GetOrCreateCache(packageName);
|
||||
cache.Record(cacheGUID, wrapper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 丢弃验证的文件(同时删除文件)
|
||||
/// </summary>
|
||||
public static void DiscardFile(string packageName, string cacheGUID)
|
||||
{
|
||||
var cache = GetOrCreateCache(packageName);
|
||||
var wrapper = cache.TryGetWrapper(cacheGUID);
|
||||
if (wrapper == null)
|
||||
return;
|
||||
|
||||
cache.Discard(cacheGUID);
|
||||
|
||||
try
|
||||
{
|
||||
string filePath = patchBundle.CachedFilePath;
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedDic.Remove(cacheKey);
|
||||
YooLogger.Error($"Cache file is missing : {filePath}");
|
||||
return false;
|
||||
}
|
||||
string dataFilePath = wrapper.DataFilePath;
|
||||
FileInfo fileInfo = new FileInfo(dataFilePath);
|
||||
if (fileInfo.Exists)
|
||||
fileInfo.Directory.Delete(true);
|
||||
}
|
||||
else
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
YooLogger.Error($"Failed to delete cache file ! {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存补丁包文件
|
||||
/// 验证缓存文件(子线程内操作)
|
||||
/// </summary>
|
||||
public static void CacheBundle(PatchBundle patchBundle)
|
||||
public static EVerifyResult VerifyingCacheFile(VerifyElement element, EVerifyLevel verifyLevel)
|
||||
{
|
||||
string cacheKey = patchBundle.CacheKey;
|
||||
if (_cachedDic.ContainsKey(cacheKey) == false)
|
||||
try
|
||||
{
|
||||
string filePath = patchBundle.CachedFilePath;
|
||||
YooLogger.Log($"Cache verify file : {filePath}");
|
||||
_cachedDic.Add(cacheKey, patchBundle);
|
||||
string infoFilePath = element.InfoFilePath;
|
||||
if (File.Exists(infoFilePath) == false)
|
||||
return EVerifyResult.InfoFileNotExisted;
|
||||
|
||||
// 解析信息文件获取验证数据
|
||||
string jsonContent = FileUtility.ReadAllText(infoFilePath);
|
||||
CacheFileInfo fileInfo = UnityEngine.JsonUtility.FromJson<CacheFileInfo>(jsonContent);
|
||||
element.DataFileCRC = fileInfo.FileCRC;
|
||||
element.DataFileSize = fileInfo.FileSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证补丁包文件
|
||||
/// </summary>
|
||||
public static EVerifyResult VerifyBundle(PatchBundle patchBundle, EVerifyLevel verifyLevel)
|
||||
{
|
||||
return VerifyContentInternal(patchBundle.CachedFilePath, patchBundle.FileSize, patchBundle.FileCRC, verifyLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证并缓存本地文件
|
||||
/// </summary>
|
||||
public static EVerifyResult VerifyAndCacheLocalBundleFile(PatchBundle patchBundle, EVerifyLevel verifyLevel)
|
||||
{
|
||||
var verifyResult = VerifyContentInternal(patchBundle.CachedFilePath, patchBundle.FileSize, patchBundle.FileCRC, verifyLevel);
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
CacheBundle(patchBundle);
|
||||
return verifyResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证并缓存下载文件
|
||||
/// </summary>
|
||||
public static EVerifyResult VerifyAndCacheDownloadBundleFile(string tempFilePath, PatchBundle patchBundle, EVerifyLevel verifyLevel)
|
||||
{
|
||||
var verifyResult = VerifyContentInternal(tempFilePath, patchBundle.FileSize, patchBundle.FileCRC, verifyLevel);
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
string destFilePath = patchBundle.CachedFilePath;
|
||||
if (File.Exists(destFilePath))
|
||||
File.Delete(destFilePath);
|
||||
return EVerifyResult.Exception;
|
||||
}
|
||||
|
||||
FileInfo fileInfo = new FileInfo(tempFilePath);
|
||||
fileInfo.MoveTo(destFilePath);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
verifyResult = EVerifyResult.FileMoveFailed;
|
||||
}
|
||||
return VerifyingInternal(element.DataFilePath, element.DataFileSize, element.DataFileCRC, verifyLevel);
|
||||
}
|
||||
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
/// <summary>
|
||||
/// 验证下载文件
|
||||
/// </summary>
|
||||
public static EVerifyResult VerifyingTempFile(PatchBundle patchBundle, EVerifyLevel verifyLevel)
|
||||
{
|
||||
return VerifyingInternal(patchBundle.TempDataFilePath, patchBundle.FileSize, patchBundle.FileCRC, verifyLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证记录文件
|
||||
/// </summary>
|
||||
public static EVerifyResult VerifyingRecordFile(string packageName, string cacheGUID)
|
||||
{
|
||||
var cache = GetOrCreateCache(packageName);
|
||||
var wrapper = cache.TryGetWrapper(cacheGUID);
|
||||
if (wrapper == null)
|
||||
return EVerifyResult.CacheNotFound;
|
||||
|
||||
EVerifyResult result = VerifyingInternal(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EVerifyLevel.High);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取未被使用的缓存文件
|
||||
/// </summary>
|
||||
public static List<string> GetUnusedCacheGUIDs(AssetsPackage package)
|
||||
{
|
||||
var cache = GetOrCreateCache(package.PackageName);
|
||||
var keys = cache.GetAllKeys();
|
||||
List<string> result = new List<string>(keys.Count);
|
||||
foreach (var cacheGUID in keys)
|
||||
{
|
||||
if (package.IsIncludeBundleFile(cacheGUID) == false)
|
||||
{
|
||||
CacheBundle(patchBundle);
|
||||
result.Add(cacheGUID);
|
||||
}
|
||||
}
|
||||
return verifyResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证文件完整性
|
||||
/// </summary>
|
||||
private static EVerifyResult VerifyContentInternal(string filePath, long fileSize, string fileCRC, EVerifyLevel verifyLevel)
|
||||
|
||||
private static EVerifyResult VerifyingInternal(string filePath, long fileSize, string fileCRC, EVerifyLevel verifyLevel)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(filePath) == false)
|
||||
return EVerifyResult.FileNotExisted;
|
||||
return EVerifyResult.DataFileNotExisted;
|
||||
|
||||
// 先验证文件大小
|
||||
long size = FileUtility.GetFileSize(filePath);
|
||||
|
@ -149,5 +165,14 @@ namespace YooAsset
|
|||
return EVerifyResult.Exception;
|
||||
}
|
||||
}
|
||||
private static PackageCache GetOrCreateCache(string packageName)
|
||||
{
|
||||
if (_cachedDic.TryGetValue(packageName, out PackageCache cache) == false)
|
||||
{
|
||||
cache = new PackageCache(packageName);
|
||||
_cachedDic.Add(packageName, cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,14 +7,19 @@ namespace YooAsset
|
|||
internal enum EVerifyResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件不存在
|
||||
/// 未找到缓存信息
|
||||
/// </summary>
|
||||
FileNotExisted = -5,
|
||||
CacheNotFound = -6,
|
||||
|
||||
/// <summary>
|
||||
/// 文件移动失败(重命名失败)
|
||||
/// 信息文件不存在
|
||||
/// </summary>
|
||||
FileMoveFailed = -4,
|
||||
InfoFileNotExisted = -5,
|
||||
|
||||
/// <summary>
|
||||
/// 数据文件不存在
|
||||
/// </summary>
|
||||
DataFileNotExisted = -4,
|
||||
|
||||
/// <summary>
|
||||
/// 文件内容不足(小于正常大小)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d29a9623b2b346e439b7a7e37fafa781
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,71 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 清理本地包裹未使用的缓存文件
|
||||
/// </summary>
|
||||
public sealed class ClearUnusedCacheFilesOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
GetUnusedCacheFiles,
|
||||
ClearUnusedCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly AssetsPackage _package;
|
||||
private List<string> _unusedCacheGUIDs;
|
||||
private int _unusedFileTotalCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal ClearUnusedCacheFilesOperation(AssetsPackage package)
|
||||
{
|
||||
_package = package;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.GetUnusedCacheFiles;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.GetUnusedCacheFiles)
|
||||
{
|
||||
_unusedCacheGUIDs = CacheSystem.GetUnusedCacheGUIDs(_package);
|
||||
_unusedFileTotalCount = _unusedCacheGUIDs.Count;
|
||||
YooLogger.Log($"Found unused cache file count : {_unusedFileTotalCount}");
|
||||
_steps = ESteps.ClearUnusedCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearUnusedCacheFiles)
|
||||
{
|
||||
for (int i = _unusedCacheGUIDs.Count - 1; i >= 0; i--)
|
||||
{
|
||||
string cacheGUID = _unusedCacheGUIDs[i];
|
||||
CacheSystem.DiscardFile(_package.PackageName, cacheGUID);
|
||||
_unusedCacheGUIDs.RemoveAt(i);
|
||||
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_unusedFileTotalCount == 0)
|
||||
Progress = 1.0f;
|
||||
else
|
||||
Progress = 1.0f - (_unusedCacheGUIDs.Count / _unusedFileTotalCount);
|
||||
|
||||
if (_unusedCacheGUIDs.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class PackageCachingOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
GetCacheFiles,
|
||||
VerifyCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly string _packageName;
|
||||
private PackageVerifyOperation _packageVerifyOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public PackageCachingOperation(string packageName)
|
||||
{
|
||||
_packageName = packageName;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.GetCacheFiles;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.GetCacheFiles)
|
||||
{
|
||||
var elements = GetVerifyElements();
|
||||
_packageVerifyOp = PackageVerifyOperation.CreateOperation(elements);
|
||||
OperationSystem.StartOperation(_packageVerifyOp);
|
||||
_steps = ESteps.VerifyCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyCacheFiles)
|
||||
{
|
||||
Progress = _packageVerifyOp.Progress;
|
||||
if (_packageVerifyOp.IsDone == false)
|
||||
return;
|
||||
|
||||
// 注意:总是返回成功
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
|
||||
private List<VerifyElement> GetVerifyElements()
|
||||
{
|
||||
string cacheFolderPath = PersistentHelper.GetCacheFolderPath(_packageName);
|
||||
if (Directory.Exists(cacheFolderPath) == false)
|
||||
return new List<VerifyElement>();
|
||||
|
||||
DirectoryInfo rootDirectory = new DirectoryInfo(cacheFolderPath);
|
||||
DirectoryInfo[] fileFolders = rootDirectory.GetDirectories();
|
||||
List<VerifyElement> result = new List<VerifyElement>(fileFolders.Length);
|
||||
foreach (var fileFoder in fileFolders)
|
||||
{
|
||||
string cacheGUID = fileFoder.Name;
|
||||
if (CacheSystem.IsCached(_packageName, cacheGUID))
|
||||
continue;
|
||||
|
||||
string fileRootPath = fileFoder.FullName;
|
||||
string dataFilePath = $"{fileRootPath}/{ YooAssetSettings.CacheBundleDataFileName}";
|
||||
string infoFilePath = $"{fileRootPath}/{ YooAssetSettings.CacheBundleInfoFileName}";
|
||||
VerifyElement element = new VerifyElement(_packageName, cacheGUID, fileRootPath, dataFilePath, infoFilePath);
|
||||
result.Add(element);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d400b2548d79ca42bec7370f5d66b78
|
||||
guid: 4ff95e7516dbfa148b4fe16eaab783fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -0,0 +1,258 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class PackageVerifyOperation : AsyncOperationBase
|
||||
{
|
||||
public static PackageVerifyOperation CreateOperation(List<VerifyElement> elements)
|
||||
{
|
||||
#if UNITY_WEBGL
|
||||
var operation = new PackageVerifyWithoutThreadOperation(elements);
|
||||
#else
|
||||
var operation = new PackageVerifyWithThreadOperation(elements);
|
||||
#endif
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地缓存文件验证(线程版)
|
||||
/// </summary>
|
||||
internal class PackageVerifyWithThreadOperation : PackageVerifyOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
InitVerify,
|
||||
UpdateVerify,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly ThreadSyncContext _syncContext = new ThreadSyncContext();
|
||||
private List<VerifyElement> _waitingList;
|
||||
private List<VerifyElement> _verifyingList;
|
||||
private int _verifyMaxNum;
|
||||
private int _verifyTotalCount;
|
||||
private float _verifyStartTime;
|
||||
private int _succeedCount;
|
||||
private int _failedCount;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public PackageVerifyWithThreadOperation(List<VerifyElement> elements)
|
||||
{
|
||||
_waitingList = elements;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.InitVerify;
|
||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.InitVerify)
|
||||
{
|
||||
int fileCount = _waitingList.Count;
|
||||
|
||||
// 设置同时验证的最大数
|
||||
ThreadPool.GetMaxThreads(out int workerThreads, out int ioThreads);
|
||||
YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
|
||||
_verifyMaxNum = Math.Min(workerThreads, ioThreads);
|
||||
_verifyTotalCount = fileCount;
|
||||
if (_verifyMaxNum < 1)
|
||||
_verifyMaxNum = 1;
|
||||
|
||||
_verifyingList = new List<VerifyElement>(_verifyMaxNum);
|
||||
_steps = ESteps.UpdateVerify;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerify)
|
||||
{
|
||||
_syncContext.Update();
|
||||
|
||||
Progress = GetProgress();
|
||||
if (_waitingList.Count == 0 && _verifyingList.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyStartTime;
|
||||
YooLogger.Log($"Package verify elapsed time {costTime:f1} seconds");
|
||||
}
|
||||
|
||||
for (int i = _waitingList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
|
||||
if (_verifyingList.Count >= _verifyMaxNum)
|
||||
break;
|
||||
|
||||
var element = _waitingList[i];
|
||||
if (BeginVerifyFileWithThread(element))
|
||||
{
|
||||
_waitingList.RemoveAt(i);
|
||||
_verifyingList.Add(element);
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Warning("The thread pool is failed queued.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float GetProgress()
|
||||
{
|
||||
if (_verifyTotalCount == 0)
|
||||
return 1f;
|
||||
return (float)(_succeedCount + _failedCount) / _verifyTotalCount;
|
||||
}
|
||||
private bool BeginVerifyFileWithThread(VerifyElement element)
|
||||
{
|
||||
return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), element);
|
||||
}
|
||||
private void VerifyInThread(object obj)
|
||||
{
|
||||
VerifyElement element = (VerifyElement)obj;
|
||||
element.Result = CacheSystem.VerifyingCacheFile(element, CacheSystem.InitVerifyLevel);
|
||||
_syncContext.Post(VerifyCallback, element);
|
||||
}
|
||||
private void VerifyCallback(object obj)
|
||||
{
|
||||
VerifyElement element = (VerifyElement)obj;
|
||||
_verifyingList.Remove(element);
|
||||
|
||||
if (element.Result == EVerifyResult.Succeed)
|
||||
{
|
||||
_succeedCount++;
|
||||
var wrapper = new PackageCache.RecordWrapper(element.InfoFilePath, element.DataFilePath, element.DataFileCRC, element.DataFileSize);
|
||||
CacheSystem.RecordFile(element.PackageName, element.CacheGUID, wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
_failedCount++;
|
||||
|
||||
// 删除验证失败的缓存文件
|
||||
if (Directory.Exists(element.FileRootPath))
|
||||
{
|
||||
YooLogger.Warning($"Failed verify file and delete files : {element.FileRootPath}");
|
||||
Directory.Delete(element.FileRootPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地缓存文件验证(非线程版)
|
||||
/// </summary>
|
||||
internal class PackageVerifyWithoutThreadOperation : PackageVerifyOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
InitVerify,
|
||||
UpdateVerify,
|
||||
Done,
|
||||
}
|
||||
|
||||
private List<VerifyElement> _waitingList;
|
||||
private List<VerifyElement> _verifyingList;
|
||||
private int _verifyMaxNum;
|
||||
private int _verifyTotalCount;
|
||||
private float _verifyStartTime;
|
||||
private int _succeedCount;
|
||||
private int _failedCount;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public PackageVerifyWithoutThreadOperation(List<VerifyElement> elements)
|
||||
{
|
||||
_waitingList = elements;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.InitVerify;
|
||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.InitVerify)
|
||||
{
|
||||
int fileCount = _waitingList.Count;
|
||||
|
||||
// 设置同时验证的最大数
|
||||
_verifyMaxNum = fileCount;
|
||||
_verifyTotalCount = fileCount;
|
||||
|
||||
_verifyingList = new List<VerifyElement>(_verifyMaxNum);
|
||||
_steps = ESteps.UpdateVerify;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerify)
|
||||
{
|
||||
Progress = GetProgress();
|
||||
if (_waitingList.Count == 0 && _verifyingList.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyStartTime;
|
||||
YooLogger.Log($"Package verify elapsed time {costTime:f1} seconds");
|
||||
}
|
||||
|
||||
for (int i = _waitingList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
|
||||
if (_verifyingList.Count >= _verifyMaxNum)
|
||||
break;
|
||||
|
||||
var element = _waitingList[i];
|
||||
BeginVerifyFileWithoutThread(element);
|
||||
_waitingList.RemoveAt(i);
|
||||
_verifyingList.Add(element);
|
||||
}
|
||||
|
||||
// 主线程内验证,可以清空列表
|
||||
_verifyingList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private float GetProgress()
|
||||
{
|
||||
if (_verifyTotalCount == 0)
|
||||
return 1f;
|
||||
return (float)(_succeedCount + _failedCount) / _verifyTotalCount;
|
||||
}
|
||||
private void BeginVerifyFileWithoutThread(VerifyElement element)
|
||||
{
|
||||
element.Result = CacheSystem.VerifyingCacheFile(element, CacheSystem.InitVerifyLevel);
|
||||
if (element.Result == EVerifyResult.Succeed)
|
||||
{
|
||||
_succeedCount++;
|
||||
var wrapper = new PackageCache.RecordWrapper(element.InfoFilePath, element.DataFilePath, element.DataFileCRC, element.DataFileSize);
|
||||
CacheSystem.RecordFile(element.PackageName, element.CacheGUID, wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
_failedCount++;
|
||||
|
||||
// 删除验证失败的缓存文件
|
||||
if (Directory.Exists(element.FileRootPath))
|
||||
{
|
||||
YooLogger.Warning($"Failed verify file and delete files : {element.FileRootPath}");
|
||||
Directory.Delete(element.FileRootPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class PackageCache
|
||||
{
|
||||
internal class RecordWrapper
|
||||
{
|
||||
public string InfoFilePath { private set; get; }
|
||||
public string DataFilePath { private set; get; }
|
||||
public string DataFileCRC { private set; get; }
|
||||
public long DataFileSize { private set; get; }
|
||||
|
||||
public RecordWrapper(string infoFilePath, string dataFilePath, string dataFileCRC, long dataFileSize)
|
||||
{
|
||||
InfoFilePath = infoFilePath;
|
||||
DataFilePath = dataFilePath;
|
||||
DataFileCRC = dataFileCRC;
|
||||
DataFileSize = dataFileSize;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, RecordWrapper> _wrappers = new Dictionary<string, RecordWrapper>();
|
||||
|
||||
/// <summary>
|
||||
/// 包裹名称
|
||||
/// </summary>
|
||||
public string PackageName { private set; get; }
|
||||
|
||||
|
||||
public PackageCache(string packageName)
|
||||
{
|
||||
PackageName = packageName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空所有数据
|
||||
/// </summary>
|
||||
public void ClearAll()
|
||||
{
|
||||
_wrappers.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询缓存记录
|
||||
/// </summary>
|
||||
public bool IsCached(string cacheGUID)
|
||||
{
|
||||
return _wrappers.ContainsKey(cacheGUID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录验证结果
|
||||
/// </summary>
|
||||
public void Record(string cacheGUID, RecordWrapper wrapper)
|
||||
{
|
||||
if (_wrappers.ContainsKey(cacheGUID) == false)
|
||||
{
|
||||
_wrappers.Add(cacheGUID, wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Should never get here !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 丢弃验证结果
|
||||
/// </summary>
|
||||
public void Discard(string cacheGUID)
|
||||
{
|
||||
if (_wrappers.ContainsKey(cacheGUID))
|
||||
{
|
||||
_wrappers.Remove(cacheGUID);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取记录对象
|
||||
/// </summary>
|
||||
public RecordWrapper TryGetWrapper(string cacheGUID)
|
||||
{
|
||||
if (_wrappers.TryGetValue(cacheGUID, out RecordWrapper value))
|
||||
return value;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
internal List<string> GetAllKeys()
|
||||
{
|
||||
List<string> keys = new List<string>(_wrappers.Keys.Count);
|
||||
var keyCollection = _wrappers.Keys;
|
||||
foreach (var key in keyCollection)
|
||||
{
|
||||
keys.Add(key);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 08f3e92fdbd5d56459d8882be1f54f60
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class VerifyElement
|
||||
{
|
||||
public string PackageName { private set; get; }
|
||||
public string CacheGUID { private set; get; }
|
||||
public string FileRootPath { private set; get; }
|
||||
public string DataFilePath { private set; get; }
|
||||
public string InfoFilePath { private set; get; }
|
||||
|
||||
public EVerifyResult Result;
|
||||
public string DataFileCRC;
|
||||
public long DataFileSize;
|
||||
|
||||
public VerifyElement(string packageName, string cacheGUID, string fileRootPath, string dataFilePath, string infoFilePath)
|
||||
{
|
||||
PackageName = packageName;
|
||||
CacheGUID = cacheGUID;
|
||||
FileRootPath = fileRootPath;
|
||||
DataFilePath = dataFilePath;
|
||||
InfoFilePath = infoFilePath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5a4b96484bd701f4289b2f74c38abaa8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,33 +0,0 @@
|
|||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class VerifyInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证的资源文件是否为内置资源
|
||||
/// </summary>
|
||||
public bool IsBuildinFile { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证的资源包实例
|
||||
/// </summary>
|
||||
public PatchBundle VerifyBundle { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证的文件路径
|
||||
/// </summary>
|
||||
public string VerifyFilePath { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证结果
|
||||
/// </summary>
|
||||
public EVerifyResult Result;
|
||||
|
||||
public VerifyInfo(bool isBuildinFile, PatchBundle verifyBundle)
|
||||
{
|
||||
IsBuildinFile = isBuildinFile;
|
||||
VerifyBundle = verifyBundle;
|
||||
VerifyFilePath = verifyBundle.CachedFilePath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -77,13 +77,13 @@ namespace YooAsset
|
|||
public static DownloaderBase BeginDownload(BundleInfo bundleInfo, int failedTryAgain, int timeout = 60)
|
||||
{
|
||||
// 查询存在的下载器
|
||||
if (_downloaderDic.TryGetValue(bundleInfo.Bundle.CachedFilePath, out var downloader))
|
||||
if (_downloaderDic.TryGetValue(bundleInfo.Bundle.CachedDataFilePath, out var downloader))
|
||||
{
|
||||
return downloader;
|
||||
}
|
||||
|
||||
// 如果资源已经缓存
|
||||
if (CacheSystem.IsCached(bundleInfo.Bundle))
|
||||
if (CacheSystem.IsCached(bundleInfo.Bundle.PackageName, bundleInfo.Bundle.CacheGUID))
|
||||
{
|
||||
var tempDownloader = new TempDownloader(bundleInfo);
|
||||
return tempDownloader;
|
||||
|
@ -92,11 +92,11 @@ namespace YooAsset
|
|||
// 创建新的下载器
|
||||
{
|
||||
YooLogger.Log($"Beginning to download file : {bundleInfo.Bundle.FileName} URL : {bundleInfo.RemoteMainURL}");
|
||||
FileUtility.CreateFileDirectory(bundleInfo.Bundle.CachedFilePath);
|
||||
FileUtility.CreateFileDirectory(bundleInfo.Bundle.CachedDataFilePath);
|
||||
bool breakDownload = bundleInfo.Bundle.FileSize >= BreakpointResumeFileSize;
|
||||
DownloaderBase newDownloader = new FileDownloader(bundleInfo, breakDownload);
|
||||
newDownloader.SendRequest(failedTryAgain, timeout);
|
||||
_downloaderDic.Add(bundleInfo.Bundle.CachedFilePath, newDownloader);
|
||||
_downloaderDic.Add(bundleInfo.Bundle.CachedDataFilePath, newDownloader);
|
||||
return newDownloader;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@ namespace YooAsset
|
|||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckLocalFile,
|
||||
CheckTempFile,
|
||||
PrepareDownload,
|
||||
CreateResumeDownloader,
|
||||
CreateGeneralDownloader,
|
||||
CheckDownload,
|
||||
VerifyDownload,
|
||||
VerifyingFile,
|
||||
CachingFile,
|
||||
TryAgain,
|
||||
Succeed,
|
||||
Failed,
|
||||
|
@ -60,7 +60,7 @@ namespace YooAsset
|
|||
{
|
||||
_failedTryAgain = failedTryAgain;
|
||||
_timeout = timeout;
|
||||
_steps = ESteps.CheckLocalFile;
|
||||
_steps = ESteps.CheckTempFile;
|
||||
}
|
||||
}
|
||||
public abstract void Update();
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace YooAsset
|
|||
public FileDownloader(BundleInfo bundleInfo, bool breakResume) : base(bundleInfo)
|
||||
{
|
||||
_breakResume = breakResume;
|
||||
_tempFilePath = bundleInfo.Bundle.CachedFilePath + ".temp";
|
||||
_tempFilePath = bundleInfo.Bundle.TempDataFilePath;
|
||||
}
|
||||
public override void Update()
|
||||
{
|
||||
|
@ -34,29 +34,13 @@ namespace YooAsset
|
|||
if (IsDone())
|
||||
return;
|
||||
|
||||
// 检测本地正式文件
|
||||
if (_steps == ESteps.CheckLocalFile)
|
||||
{
|
||||
var verifyResult = CacheSystem.VerifyAndCacheLocalBundleFile(_bundleInfo.Bundle, CacheSystem.InitVerifyLevel);
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
{
|
||||
_steps = ESteps.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (File.Exists(_bundleInfo.Bundle.CachedFilePath))
|
||||
File.Delete(_bundleInfo.Bundle.CachedFilePath);
|
||||
_steps = ESteps.CheckTempFile;
|
||||
}
|
||||
}
|
||||
|
||||
// 检测本地临时文件
|
||||
if (_steps == ESteps.CheckTempFile)
|
||||
{
|
||||
var verifyResult = CacheSystem.VerifyAndCacheDownloadBundleFile(_tempFilePath, _bundleInfo.Bundle, EVerifyLevel.High);
|
||||
var verifyResult = CacheSystem.VerifyingTempFile(_bundleInfo.Bundle, EVerifyLevel.High);
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
{
|
||||
_steps = ESteps.Succeed;
|
||||
_steps = ESteps.CachingFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -94,9 +78,7 @@ namespace YooAsset
|
|||
if (_steps == ESteps.CreateGeneralDownloader)
|
||||
{
|
||||
if (File.Exists(_tempFilePath))
|
||||
{
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
|
||||
_webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET);
|
||||
DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath);
|
||||
|
@ -206,7 +188,7 @@ namespace YooAsset
|
|||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.VerifyDownload;
|
||||
_steps = ESteps.VerifyingFile;
|
||||
}
|
||||
|
||||
// 释放下载器
|
||||
|
@ -214,23 +196,55 @@ namespace YooAsset
|
|||
}
|
||||
|
||||
// 验证下载文件
|
||||
if (_steps == ESteps.VerifyDownload)
|
||||
if (_steps == ESteps.VerifyingFile)
|
||||
{
|
||||
var verifyResult = CacheSystem.VerifyAndCacheDownloadBundleFile(_tempFilePath, _bundleInfo.Bundle, EVerifyLevel.High);
|
||||
var verifyResult = CacheSystem.VerifyingTempFile(_bundleInfo.Bundle, EVerifyLevel.High);
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
{
|
||||
_steps = ESteps.CachingFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastError = $"Failed to verifying file : {_bundleInfo.Bundle.FileName}, ErrorCode : {verifyResult}";
|
||||
|
||||
// 注意:验证失败后删除文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
|
||||
_steps = ESteps.TryAgain;
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存下载文件
|
||||
if (_steps == ESteps.CachingFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
string destFilePath = _bundleInfo.Bundle.CachedDataFilePath;
|
||||
if (File.Exists(destFilePath))
|
||||
File.Delete(destFilePath);
|
||||
|
||||
FileInfo fileInfo = new FileInfo(_tempFilePath);
|
||||
fileInfo.MoveTo(destFilePath);
|
||||
|
||||
// 写入信息文件记录验证数据
|
||||
CacheFileInfo cacheInfo = new CacheFileInfo();
|
||||
cacheInfo.FileCRC = _bundleInfo.Bundle.FileCRC;
|
||||
cacheInfo.FileSize = _bundleInfo.Bundle.FileSize;
|
||||
string jsonContent = UnityEngine.JsonUtility.ToJson(cacheInfo);
|
||||
FileUtility.CreateFile(_bundleInfo.Bundle.CachedInfoFilePath, jsonContent);
|
||||
|
||||
// 记录缓存文件
|
||||
var wrapper = new PackageCache.RecordWrapper(_bundleInfo.Bundle.CachedInfoFilePath, _bundleInfo.Bundle.CachedDataFilePath, _bundleInfo.Bundle.FileCRC, _bundleInfo.Bundle.FileSize);
|
||||
CacheSystem.RecordFile(_bundleInfo.Bundle.PackageName, _bundleInfo.Bundle.CacheGUID, wrapper);
|
||||
|
||||
_lastError = string.Empty;
|
||||
_lastCode = 0;
|
||||
_steps = ESteps.Succeed;
|
||||
}
|
||||
else
|
||||
catch (Exception e)
|
||||
{
|
||||
_lastError = $"Verify bundle content failed : {_bundleInfo.Bundle.FileName}";
|
||||
|
||||
// 验证失败后删除文件
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
|
||||
_lastError = e.Message;
|
||||
_steps = ESteps.TryAgain;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 检查包裹内容的完整性
|
||||
/// </summary>
|
||||
public abstract class CheckPackageContentsOperation : AsyncOperationBase
|
||||
{
|
||||
}
|
||||
|
||||
internal sealed class EditorSimulateModeCheckPackageContentsOperation : CheckPackageContentsOperation
|
||||
{
|
||||
internal EditorSimulateModeCheckPackageContentsOperation()
|
||||
{
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
internal sealed class OfflinePlayModeCheckPackageContentsOperation : CheckPackageContentsOperation
|
||||
{
|
||||
internal OfflinePlayModeCheckPackageContentsOperation()
|
||||
{
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
internal sealed class HostPlayModeCheckPackageContentsOperation : CheckPackageContentsOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckActiveManifest,
|
||||
LoadCacheManifest,
|
||||
VerifyPackage,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly HostPlayModeImpl _impl;
|
||||
private readonly string _packageName;
|
||||
private readonly string _packageVersion;
|
||||
private LoadCacheManifestOperation _loadCacheManifestOp;
|
||||
private VerifyPackageOperation _verifyOperation;
|
||||
private PatchManifest _verifyManifest;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal HostPlayModeCheckPackageContentsOperation(HostPlayModeImpl impl, string packageName, string packageVersion)
|
||||
{
|
||||
_impl = impl;
|
||||
_packageName = packageName;
|
||||
_packageVersion = packageVersion;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.CheckActiveManifest;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckActiveManifest)
|
||||
{
|
||||
// 检测当前激活的清单对象
|
||||
if (_impl.ActiveManifest != null && _impl.ActiveManifest.PackageVersion == _packageVersion)
|
||||
{
|
||||
_verifyManifest = _impl.ActiveManifest;
|
||||
_steps = ESteps.VerifyPackage;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.LoadCacheManifest;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadCacheManifest)
|
||||
{
|
||||
if (_loadCacheManifestOp == null)
|
||||
{
|
||||
_loadCacheManifestOp = new LoadCacheManifestOperation(_packageName, _packageVersion);
|
||||
OperationSystem.StartOperation(_loadCacheManifestOp);
|
||||
}
|
||||
|
||||
if (_loadCacheManifestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadCacheManifestOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_verifyManifest = _loadCacheManifestOp.Manifest;
|
||||
_steps = ESteps.VerifyPackage;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadCacheManifestOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyPackage)
|
||||
{
|
||||
if (_verifyOperation == null)
|
||||
{
|
||||
_verifyOperation = VerifyPackageOperation.CreateOperation(_verifyManifest, _impl);
|
||||
OperationSystem.StartOperation(_verifyOperation);
|
||||
}
|
||||
|
||||
Progress = _verifyOperation.Progress;
|
||||
if (_verifyOperation.IsDone == false)
|
||||
return;
|
||||
|
||||
bool verifySucceed = true;
|
||||
foreach (var verifyInfo in _verifyOperation.VerifyFailList)
|
||||
{
|
||||
// 注意:跳过内置资源文件
|
||||
if (verifyInfo.IsBuildinFile)
|
||||
continue;
|
||||
|
||||
verifySucceed = false;
|
||||
YooLogger.Warning($"Failed verify file : {verifyInfo.VerifyFilePath}");
|
||||
}
|
||||
|
||||
if (verifySucceed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"The package resource {_packageName} content has verify failed file !";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 清理本地包裹未使用的缓存文件
|
||||
/// </summary>
|
||||
public sealed class ClearUnusedCacheFilesOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
GetUnusedCacheFiles,
|
||||
ClearUnusedCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly AssetsPackage _package;
|
||||
private List<string> _unusedCacheFilePaths;
|
||||
private int _unusedFileTotalCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal ClearUnusedCacheFilesOperation(AssetsPackage package)
|
||||
{
|
||||
_package = package;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.GetUnusedCacheFiles;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.GetUnusedCacheFiles)
|
||||
{
|
||||
_unusedCacheFilePaths = GetUnusedCacheFilePaths();
|
||||
_unusedFileTotalCount = _unusedCacheFilePaths.Count;
|
||||
YooLogger.Log($"Found unused cache file count : {_unusedFileTotalCount}");
|
||||
_steps = ESteps.ClearUnusedCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.ClearUnusedCacheFiles)
|
||||
{
|
||||
for (int i = _unusedCacheFilePaths.Count - 1; i >= 0; i--)
|
||||
{
|
||||
string filePath = _unusedCacheFilePaths[i];
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(filePath);
|
||||
YooLogger.Log($"Delete unused cache file : {filePath}");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
YooLogger.Warning($"Failed delete cache file : {filePath} ! {e.Message}");
|
||||
}
|
||||
}
|
||||
_unusedCacheFilePaths.RemoveAt(i);
|
||||
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
}
|
||||
|
||||
if (_unusedFileTotalCount == 0)
|
||||
Progress = 1.0f;
|
||||
else
|
||||
Progress = 1.0f - (_unusedCacheFilePaths.Count / _unusedFileTotalCount);
|
||||
|
||||
if (_unusedCacheFilePaths.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取未被使用的缓存文件路径集合
|
||||
/// </summary>
|
||||
private List<string> GetUnusedCacheFilePaths()
|
||||
{
|
||||
string cacheFolderPath = PersistentHelper.GetCacheFolderPath(_package.PackageName);
|
||||
if (Directory.Exists(cacheFolderPath) == false)
|
||||
return new List<string>();
|
||||
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(cacheFolderPath);
|
||||
FileInfo[] fileInfos = directoryInfo.GetFiles();
|
||||
List<string> result = new List<string>(fileInfos.Length);
|
||||
foreach (FileInfo fileInfo in fileInfos)
|
||||
{
|
||||
if (_package.IsIncludeBundleFile(fileInfo.Name) == false)
|
||||
{
|
||||
result.Add(fileInfo.FullName);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -79,7 +79,7 @@ namespace YooAsset
|
|||
None,
|
||||
QueryBuildinPackageVersion,
|
||||
LoadBuildinManifest,
|
||||
VerifyPackage,
|
||||
PackageCaching,
|
||||
Done,
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ namespace YooAsset
|
|||
private readonly string _packageName;
|
||||
private QueryBuildinPackageVersionOperation _queryBuildinPackageVersionOp;
|
||||
private LoadBuildinManifestOperation _loadBuildinManifestOp;
|
||||
private VerifyPackageOperation _verifyOperation;
|
||||
private PackageCachingOperation _cachingOperation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal OfflinePlayModeInitializationOperation(OfflinePlayModeImpl impl, string packageName)
|
||||
|
@ -143,7 +143,7 @@ namespace YooAsset
|
|||
{
|
||||
PackageVersion = _loadBuildinManifestOp.Manifest.PackageVersion;
|
||||
_impl.ActiveManifest = _loadBuildinManifestOp.Manifest;
|
||||
_steps = ESteps.VerifyPackage;
|
||||
_steps = ESteps.PackageCaching;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -153,16 +153,16 @@ namespace YooAsset
|
|||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyPackage)
|
||||
if (_steps == ESteps.PackageCaching)
|
||||
{
|
||||
if (_verifyOperation == null)
|
||||
if (_cachingOperation == null)
|
||||
{
|
||||
_verifyOperation = VerifyPackageOperation.CreateOperation(_impl.ActiveManifest, _impl);
|
||||
OperationSystem.StartOperation(_verifyOperation);
|
||||
_cachingOperation = new PackageCachingOperation(_packageName);
|
||||
OperationSystem.StartOperation(_cachingOperation);
|
||||
}
|
||||
|
||||
Progress = _verifyOperation.Progress;
|
||||
if (_verifyOperation.IsDone)
|
||||
Progress = _cachingOperation.Progress;
|
||||
if (_cachingOperation.IsDone)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
@ -186,7 +186,7 @@ namespace YooAsset
|
|||
QueryBuildinPackageVersion,
|
||||
UnpackBuildinManifest,
|
||||
LoadBuildinManifest,
|
||||
VerifyPackage,
|
||||
PackageCaching,
|
||||
Done,
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ namespace YooAsset
|
|||
private UnpackBuildinManifestOperation _unpackBuildinManifestOp;
|
||||
private LoadBuildinManifestOperation _loadBuildinManifestOp;
|
||||
private LoadCacheManifestOperation _loadCacheManifestOp;
|
||||
private VerifyPackageOperation _verifyOperation;
|
||||
private PackageCachingOperation _cachingOperation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal HostPlayModeInitializationOperation(HostPlayModeImpl impl, string packageName)
|
||||
|
@ -265,7 +265,7 @@ namespace YooAsset
|
|||
{
|
||||
PackageVersion = _loadCacheManifestOp.Manifest.PackageVersion;
|
||||
_impl.ActiveManifest = _loadCacheManifestOp.Manifest;
|
||||
_steps = ESteps.VerifyPackage;
|
||||
_steps = ESteps.PackageCaching;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -284,15 +284,14 @@ namespace YooAsset
|
|||
if (_queryBuildinPackageVersionOp.IsDone == false)
|
||||
return;
|
||||
|
||||
// 注意:为了兼容MOD模式,初始化动态新增的包裹的时候,如果内置清单不存在也不需要报错!
|
||||
if (_queryBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.UnpackBuildinManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
// 注意:为了兼容MOD模式,初始化动态新增的包裹的时候,如果内置清单不存在也不需要报错!
|
||||
_steps = ESteps.PackageCaching;
|
||||
string error = _queryBuildinPackageVersionOp.Error;
|
||||
YooLogger.Log($"Failed to load buildin package version file : {error}");
|
||||
}
|
||||
|
@ -337,7 +336,7 @@ namespace YooAsset
|
|||
{
|
||||
PackageVersion = _loadBuildinManifestOp.Manifest.PackageVersion;
|
||||
_impl.ActiveManifest = _loadBuildinManifestOp.Manifest;
|
||||
_steps = ESteps.VerifyPackage;
|
||||
_steps = ESteps.PackageCaching;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -347,16 +346,16 @@ namespace YooAsset
|
|||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyPackage)
|
||||
if (_steps == ESteps.PackageCaching)
|
||||
{
|
||||
if (_verifyOperation == null)
|
||||
if (_cachingOperation == null)
|
||||
{
|
||||
_verifyOperation = VerifyPackageOperation.CreateOperation(_impl.ActiveManifest, _impl);
|
||||
OperationSystem.StartOperation(_verifyOperation);
|
||||
_cachingOperation = new PackageCachingOperation(_packageName);
|
||||
OperationSystem.StartOperation(_cachingOperation);
|
||||
}
|
||||
|
||||
Progress = _verifyOperation.Progress;
|
||||
if (_verifyOperation.IsDone)
|
||||
Progress = _cachingOperation.Progress;
|
||||
if (_cachingOperation.IsDone)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
|
|
@ -1,294 +0,0 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class VerifyPackageOperation : AsyncOperationBase
|
||||
{
|
||||
public List<VerifyInfo> VerifySuccessList { protected set; get; }
|
||||
public List<VerifyInfo> VerifyFailList { protected set; get; }
|
||||
|
||||
public static VerifyPackageOperation CreateOperation(PatchManifest manifest, IPlayModeServices playModeServices)
|
||||
{
|
||||
#if UNITY_WEBGL
|
||||
VerifyPackageOperation operation = new VerifyPackageWithoutThreadOperation(manifest, playModeServices);
|
||||
#else
|
||||
VerifyPackageOperation operation = new VerifyPackageWithThreadOperation(manifest, playModeServices);
|
||||
#endif
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地缓存文件验证(线程版)
|
||||
/// </summary>
|
||||
internal class VerifyPackageWithThreadOperation : VerifyPackageOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
InitVerify,
|
||||
PrepareVerify,
|
||||
UpdateVerify,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly PatchManifest _manifest;
|
||||
private readonly IPlayModeServices _playModeServices;
|
||||
private readonly ThreadSyncContext _syncContext = new ThreadSyncContext();
|
||||
private List<VerifyInfo> _waitingList;
|
||||
private List<VerifyInfo> _verifyingList;
|
||||
private int _verifyMaxNum;
|
||||
private int _verifyTotalCount;
|
||||
private float _verifyStartTime;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public VerifyPackageWithThreadOperation(PatchManifest manifest, IPlayModeServices playModeServices)
|
||||
{
|
||||
_manifest = manifest;
|
||||
_playModeServices = playModeServices;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.InitVerify;
|
||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.InitVerify)
|
||||
{
|
||||
int bundleCount = _manifest.BundleList.Count;
|
||||
VerifySuccessList = new List<VerifyInfo>(bundleCount);
|
||||
VerifyFailList = new List<VerifyInfo>(bundleCount);
|
||||
|
||||
// 设置同时验证的最大数
|
||||
ThreadPool.GetMaxThreads(out int workerThreads, out int ioThreads);
|
||||
YooLogger.Log($"Work threads : {workerThreads}, IO threads : {ioThreads}");
|
||||
_verifyMaxNum = Math.Min(workerThreads, ioThreads);
|
||||
_verifyTotalCount = bundleCount;
|
||||
if (_verifyMaxNum < 1)
|
||||
_verifyMaxNum = 1;
|
||||
|
||||
_waitingList = new List<VerifyInfo>(bundleCount);
|
||||
_verifyingList = new List<VerifyInfo>(_verifyMaxNum);
|
||||
_steps = ESteps.PrepareVerify;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.PrepareVerify)
|
||||
{
|
||||
foreach (var patchBundle in _manifest.BundleList)
|
||||
{
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
continue;
|
||||
|
||||
bool isBuildinFile = _playModeServices.IsBuildinPatchBundle(patchBundle);
|
||||
VerifyInfo verifyInfo = new VerifyInfo(isBuildinFile, patchBundle);
|
||||
_waitingList.Add(verifyInfo);
|
||||
}
|
||||
_steps = ESteps.UpdateVerify;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerify)
|
||||
{
|
||||
_syncContext.Update();
|
||||
|
||||
Progress = GetVerifierProgress();
|
||||
if (_waitingList.Count == 0 && _verifyingList.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyStartTime;
|
||||
YooLogger.Log($"Verify elapsed time {costTime:f1} seconds");
|
||||
}
|
||||
|
||||
for (int i = _waitingList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
|
||||
if (_verifyingList.Count >= _verifyMaxNum)
|
||||
break;
|
||||
|
||||
var verifyIno = _waitingList[i];
|
||||
if (VerifyFileWithThread(verifyIno))
|
||||
{
|
||||
_waitingList.RemoveAt(i);
|
||||
_verifyingList.Add(verifyIno);
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Warning("The thread pool is failed queued.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float GetVerifierProgress()
|
||||
{
|
||||
if (_verifyTotalCount == 0)
|
||||
return 1f;
|
||||
return (float)(VerifySuccessList.Count + VerifyFailList.Count) / _verifyTotalCount;
|
||||
}
|
||||
private bool VerifyFileWithThread(VerifyInfo verifyInfo)
|
||||
{
|
||||
return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), verifyInfo);
|
||||
}
|
||||
private void VerifyInThread(object infoObj)
|
||||
{
|
||||
VerifyInfo verifyInfo = (VerifyInfo)infoObj;
|
||||
verifyInfo.Result = CacheSystem.VerifyBundle(verifyInfo.VerifyBundle, CacheSystem.InitVerifyLevel);
|
||||
_syncContext.Post(VerifyCallback, verifyInfo);
|
||||
}
|
||||
private void VerifyCallback(object obj)
|
||||
{
|
||||
VerifyInfo verifyIno = (VerifyInfo)obj;
|
||||
if (verifyIno.Result == EVerifyResult.Succeed)
|
||||
{
|
||||
VerifySuccessList.Add(verifyIno);
|
||||
CacheSystem.CacheBundle(verifyIno.VerifyBundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyFailList.Add(verifyIno);
|
||||
|
||||
// 删除验证失败的缓存文件
|
||||
if (File.Exists(verifyIno.VerifyBundle.CachedFilePath))
|
||||
{
|
||||
YooLogger.Warning($"Delete verify failed bundle file : {verifyIno.VerifyBundle.CachedFilePath}");
|
||||
File.Delete(verifyIno.VerifyBundle.CachedFilePath);
|
||||
}
|
||||
}
|
||||
_verifyingList.Remove(verifyIno);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地缓存文件验证(非线程版)
|
||||
/// </summary>
|
||||
internal class VerifyPackageWithoutThreadOperation : VerifyPackageOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
InitVerify,
|
||||
PrepareVerify,
|
||||
UpdateVerify,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly PatchManifest _manifest;
|
||||
private readonly IPlayModeServices _playModeServices;
|
||||
private List<VerifyInfo> _waitingList;
|
||||
private List<VerifyInfo> _verifyingList;
|
||||
private int _verifyMaxNum;
|
||||
private int _verifyTotalCount;
|
||||
private float _verifyStartTime;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public VerifyPackageWithoutThreadOperation(PatchManifest manifest, IPlayModeServices playModeServices)
|
||||
{
|
||||
_manifest = manifest;
|
||||
_playModeServices = playModeServices;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.InitVerify;
|
||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.InitVerify)
|
||||
{
|
||||
int bundleCount = _manifest.BundleList.Count;
|
||||
VerifySuccessList = new List<VerifyInfo>(bundleCount);
|
||||
VerifyFailList = new List<VerifyInfo>(bundleCount);
|
||||
|
||||
// 设置同时验证的最大数
|
||||
_verifyMaxNum = bundleCount;
|
||||
_verifyTotalCount = bundleCount;
|
||||
|
||||
_waitingList = new List<VerifyInfo>(bundleCount);
|
||||
_verifyingList = new List<VerifyInfo>(_verifyMaxNum);
|
||||
_steps = ESteps.PrepareVerify;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.PrepareVerify)
|
||||
{
|
||||
foreach (var patchBundle in _manifest.BundleList)
|
||||
{
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
continue;
|
||||
|
||||
bool isBuildinFile = _playModeServices.IsBuildinPatchBundle(patchBundle);
|
||||
VerifyInfo verifyInfo = new VerifyInfo(isBuildinFile, patchBundle);
|
||||
_waitingList.Add(verifyInfo);
|
||||
}
|
||||
_steps = ESteps.UpdateVerify;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerify)
|
||||
{
|
||||
Progress = GetVerifierProgress();
|
||||
if (_waitingList.Count == 0 && _verifyingList.Count == 0)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyStartTime;
|
||||
YooLogger.Log($"Verify elapsed time {costTime:f1} seconds");
|
||||
}
|
||||
|
||||
for (int i = _waitingList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (OperationSystem.IsBusy)
|
||||
break;
|
||||
|
||||
if (_verifyingList.Count >= _verifyMaxNum)
|
||||
break;
|
||||
|
||||
var verifyIno = _waitingList[i];
|
||||
VerifyFileWithoutThread(verifyIno);
|
||||
_waitingList.RemoveAt(i);
|
||||
_verifyingList.Add(verifyIno);
|
||||
}
|
||||
|
||||
_verifyingList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private float GetVerifierProgress()
|
||||
{
|
||||
if (_verifyTotalCount == 0)
|
||||
return 1f;
|
||||
return (float)(VerifySuccessList.Count + VerifyFailList.Count) / _verifyTotalCount;
|
||||
}
|
||||
private void VerifyFileWithoutThread(VerifyInfo verifyIno)
|
||||
{
|
||||
var verifyResult = CacheSystem.VerifyAndCacheLocalBundleFile(verifyIno.VerifyBundle, CacheSystem.InitVerifyLevel);
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
{
|
||||
VerifySuccessList.Add(verifyIno);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyFailList.Add(verifyIno);
|
||||
|
||||
// 删除验证失败的缓存文件
|
||||
if (File.Exists(verifyIno.VerifyBundle.CachedFilePath))
|
||||
{
|
||||
YooLogger.Warning($"Delete verify failed bundle file : {verifyIno.VerifyBundle.CachedFilePath}");
|
||||
File.Delete(verifyIno.VerifyBundle.CachedFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,7 +47,7 @@ namespace YooAsset
|
|||
|
||||
/// <summary>
|
||||
/// 联机模式的更新清单操作
|
||||
/// 注意:优先加载沙盒里缓存的清单文件,如果有变化就更新远端清单文件,并保存到本地。
|
||||
/// 注意:优先加载沙盒里缓存的清单文件,如果缓存没找到就下载远端清单文件,并保存到本地。
|
||||
/// </summary>
|
||||
internal sealed class HostPlayModeUpdatePackageManifestOperation : UpdatePackageManifestOperation
|
||||
{
|
||||
|
@ -59,7 +59,6 @@ namespace YooAsset
|
|||
DownloadManifest,
|
||||
LoadCacheManifest,
|
||||
CheckDeserializeManifest,
|
||||
VerifyPackage,
|
||||
Done,
|
||||
}
|
||||
|
||||
|
@ -70,7 +69,6 @@ namespace YooAsset
|
|||
private LoadCacheManifestOperation _tryLoadCacheManifestOp;
|
||||
private LoadCacheManifestOperation _loadCacheManifestOp;
|
||||
private DownloadManifestOperation _downloadManifestOp;
|
||||
private VerifyPackageOperation _verifyOperation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
|
@ -118,7 +116,8 @@ namespace YooAsset
|
|||
if (_tryLoadCacheManifestOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_impl.ActiveManifest = _tryLoadCacheManifestOp.Manifest;
|
||||
_steps = ESteps.VerifyPackage;
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -163,7 +162,8 @@ namespace YooAsset
|
|||
if (_loadCacheManifestOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_impl.ActiveManifest = _loadCacheManifestOp.Manifest;
|
||||
_steps = ESteps.VerifyPackage;
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -172,22 +172,6 @@ namespace YooAsset
|
|||
Error = _loadCacheManifestOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyPackage)
|
||||
{
|
||||
if (_verifyOperation == null)
|
||||
{
|
||||
_verifyOperation = VerifyPackageOperation.CreateOperation(_impl.ActiveManifest, _impl);
|
||||
OperationSystem.StartOperation(_verifyOperation);
|
||||
}
|
||||
|
||||
Progress = _verifyOperation.Progress;
|
||||
if (_verifyOperation.IsDone)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,22 +45,63 @@ namespace YooAsset
|
|||
/// <summary>
|
||||
/// 所属的包裹名称
|
||||
/// </summary>
|
||||
private string _packageName;
|
||||
public string PackageName { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存文件路径
|
||||
/// 缓存GUID
|
||||
/// </summary>
|
||||
private string _cachedFilePath;
|
||||
public string CachedFilePath
|
||||
public string CacheGUID
|
||||
{
|
||||
get { return FileHash; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存的数据文件路径
|
||||
/// </summary>
|
||||
private string _cachedDataFilePath;
|
||||
public string CachedDataFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_cachedFilePath) == false)
|
||||
return _cachedFilePath;
|
||||
if (string.IsNullOrEmpty(_cachedDataFilePath) == false)
|
||||
return _cachedDataFilePath;
|
||||
|
||||
string cacheRoot = PersistentHelper.GetCacheFolderPath(_packageName);
|
||||
_cachedFilePath = $"{cacheRoot}/{FileName}";
|
||||
return _cachedFilePath;
|
||||
string cacheRoot = PersistentHelper.GetCacheFolderPath(PackageName);
|
||||
_cachedDataFilePath = $"{cacheRoot}/{CacheGUID}/{YooAssetSettings.CacheBundleDataFileName}";
|
||||
return _cachedDataFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存的信息文件路径
|
||||
/// </summary>
|
||||
private string _cachedInfoFilePath;
|
||||
public string CachedInfoFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_cachedInfoFilePath) == false)
|
||||
return _cachedInfoFilePath;
|
||||
|
||||
string cacheRoot = PersistentHelper.GetCacheFolderPath(PackageName);
|
||||
_cachedInfoFilePath = $"{cacheRoot}/{CacheGUID}/{YooAssetSettings.CacheBundleInfoFileName}";
|
||||
return _cachedInfoFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 临时的数据文件路径
|
||||
/// </summary>
|
||||
private string _tempDataFilePath;
|
||||
public string TempDataFilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_tempDataFilePath) == false)
|
||||
return _tempDataFilePath;
|
||||
|
||||
_tempDataFilePath = $"{CachedDataFilePath}.temp";
|
||||
return _tempDataFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +122,7 @@ namespace YooAsset
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件名称
|
||||
/// 文件名称(远端文件名和内置文件名)
|
||||
/// </summary>
|
||||
private string _fileName;
|
||||
public string FileName
|
||||
|
@ -94,20 +135,6 @@ namespace YooAsset
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存查询Key
|
||||
/// </summary>
|
||||
private string _cacheKey;
|
||||
public string CacheKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_cacheKey))
|
||||
throw new Exception("Should never get here !");
|
||||
return _cacheKey;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PatchBundle()
|
||||
{
|
||||
|
@ -118,8 +145,7 @@ namespace YooAsset
|
|||
/// </summary>
|
||||
public void ParseBundle(string packageName, int nameStype)
|
||||
{
|
||||
_packageName = packageName;
|
||||
_cacheKey = $"{packageName}-{FileHash}";
|
||||
PackageName = packageName;
|
||||
_fileName = PatchManifestTools.CreateBundleFileName(nameStype, BundleName, FileHash, IsRawFile);
|
||||
}
|
||||
|
||||
|
|
|
@ -239,11 +239,11 @@ namespace YooAsset
|
|||
/// <summary>
|
||||
/// 是否包含资源文件
|
||||
/// </summary>
|
||||
public bool IsIncludeBundleFile(string fileName)
|
||||
public bool IsIncludeBundleFile(string cacheGUID)
|
||||
{
|
||||
foreach (var patchBundle in BundleList)
|
||||
{
|
||||
if (patchBundle.FileName == fileName)
|
||||
if (patchBundle.CacheGUID == cacheGUID)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -159,13 +159,13 @@ namespace YooAsset
|
|||
{
|
||||
if (nameStyle == 1) //HashName
|
||||
{
|
||||
string fileExtension = isRawFile ? YooAssetSettingsData.Setting.RawFileVariant : YooAssetSettingsData.Setting.AssetBundleFileVariant;
|
||||
string fileExtension = isRawFile ? YooAssetSettingsData.Setting.RawBundleFileVariant : YooAssetSettingsData.Setting.AssetBundleFileVariant;
|
||||
return StringUtility.Format("{0}.{1}", fileHash, fileExtension);
|
||||
}
|
||||
else if (nameStyle == 4) //BundleName_HashName
|
||||
{
|
||||
string fileName = bundleName.Remove(bundleName.LastIndexOf('.'));
|
||||
string fileExtension = isRawFile ? YooAssetSettingsData.Setting.RawFileVariant : YooAssetSettingsData.Setting.AssetBundleFileVariant;
|
||||
string fileExtension = isRawFile ? YooAssetSettingsData.Setting.RawBundleFileVariant : YooAssetSettingsData.Setting.AssetBundleFileVariant;
|
||||
return StringUtility.Format("{0}_{1}.{2}", fileName, fileHash, fileExtension);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -56,12 +56,6 @@ namespace YooAsset
|
|||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
CheckPackageContentsOperation IPlayModeServices.CheckPackageContentsOperation(string packageVersion)
|
||||
{
|
||||
var operation = new EditorSimulateModeCheckPackageContentsOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
PatchDownloaderOperation IPlayModeServices.CreatePatchDownloaderByAll(int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
|
|
|
@ -95,6 +95,10 @@ namespace YooAsset
|
|||
{
|
||||
return _queryServices.QueryStreamingAssets(patchBundle.FileName);
|
||||
}
|
||||
public bool IsCachedPatchBundle(PatchBundle patchBundle)
|
||||
{
|
||||
return CacheSystem.IsCached(patchBundle.PackageName, patchBundle.CacheGUID);
|
||||
}
|
||||
|
||||
UpdatePackageVersionOperation IPlayModeServices.UpdatePackageVersionAsync(bool appendTimeTicks, int timeout)
|
||||
{
|
||||
|
@ -114,12 +118,6 @@ namespace YooAsset
|
|||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
CheckPackageContentsOperation IPlayModeServices.CheckPackageContentsOperation(string packageVersion)
|
||||
{
|
||||
var operation = new HostPlayModeCheckPackageContentsOperation(this, _packageName, packageVersion);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
PatchDownloaderOperation IPlayModeServices.CreatePatchDownloaderByAll(int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
|
@ -133,7 +131,7 @@ namespace YooAsset
|
|||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
if (IsCachedPatchBundle(patchBundle))
|
||||
continue;
|
||||
|
||||
// 忽略APP资源
|
||||
|
@ -158,7 +156,7 @@ namespace YooAsset
|
|||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
if (IsCachedPatchBundle(patchBundle))
|
||||
continue;
|
||||
|
||||
// 忽略APP资源
|
||||
|
@ -219,7 +217,7 @@ namespace YooAsset
|
|||
foreach (var patchBundle in checkList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
if (IsCachedPatchBundle(patchBundle))
|
||||
continue;
|
||||
|
||||
// 忽略APP资源
|
||||
|
@ -244,7 +242,7 @@ namespace YooAsset
|
|||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
if (IsCachedPatchBundle(patchBundle))
|
||||
continue;
|
||||
|
||||
if (IsBuildinPatchBundle(patchBundle))
|
||||
|
@ -268,7 +266,7 @@ namespace YooAsset
|
|||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
// 忽略缓存文件
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
if (IsCachedPatchBundle(patchBundle))
|
||||
continue;
|
||||
|
||||
// 查询DLC资源
|
||||
|
@ -292,7 +290,7 @@ namespace YooAsset
|
|||
throw new Exception("Should never get here !");
|
||||
|
||||
// 查询沙盒资源
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
if (IsCachedPatchBundle(patchBundle))
|
||||
{
|
||||
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromCache);
|
||||
return bundleInfo;
|
||||
|
|
|
@ -56,12 +56,6 @@ namespace YooAsset
|
|||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
CheckPackageContentsOperation IPlayModeServices.CheckPackageContentsOperation(string packageVersion)
|
||||
{
|
||||
var operation = new OfflinePlayModeCheckPackageContentsOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
PatchDownloaderOperation IPlayModeServices.CreatePatchDownloaderByAll(int downloadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
|
@ -93,7 +87,7 @@ namespace YooAsset
|
|||
throw new Exception("Should never get here !");
|
||||
|
||||
// 查询沙盒资源
|
||||
if (CacheSystem.IsCached(patchBundle))
|
||||
if (CacheSystem.IsCached(patchBundle.PackageName, patchBundle.CacheGUID))
|
||||
{
|
||||
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromCache);
|
||||
return bundleInfo;
|
||||
|
|
|
@ -28,11 +28,6 @@ namespace YooAsset
|
|||
/// </summary>
|
||||
PreDownloadPackageOperation PreDownloadPackageAsync(string packageVersion, int timeout);
|
||||
|
||||
/// <summary>
|
||||
/// 检查包裹内容的完整性
|
||||
/// </summary>
|
||||
CheckPackageContentsOperation CheckPackageContentsOperation(string packageVersion);
|
||||
|
||||
// 下载相关
|
||||
PatchDownloaderOperation CreatePatchDownloaderByAll(int downloadingMaxNumber, int failedTryAgain, int timeout);
|
||||
PatchDownloaderOperation CreatePatchDownloaderByTags(string[] tags, int downloadingMaxNumber, int failedTryAgain, int timeout);
|
||||
|
|
|
@ -8,12 +8,12 @@ namespace YooAsset
|
|||
/// <summary>
|
||||
/// AssetBundle文件的后缀名
|
||||
/// </summary>
|
||||
public string BundleFileVariant = "bundle";
|
||||
public string AssetBundleFileVariant = "bundle";
|
||||
|
||||
/// <summary>
|
||||
/// 原生文件的后缀名
|
||||
/// </summary>
|
||||
public string RawFileVariant = "rawfile";
|
||||
public string RawBundleFileVariant = "rawfile";
|
||||
|
||||
/// <summary>
|
||||
/// 清单文件名称
|
||||
|
|
|
@ -79,9 +79,9 @@ namespace YooAsset
|
|||
{
|
||||
string shareBundleName;
|
||||
if (uniqueBundleName)
|
||||
shareBundleName = $"{packageName.ToLower()}_{YooAssetSettings.UnityShadersBundleName}.{Setting.BundleFileVariant}";
|
||||
shareBundleName = $"{packageName.ToLower()}_{YooAssetSettings.UnityShadersBundleName}.{Setting.AssetBundleFileVariant}";
|
||||
else
|
||||
shareBundleName = $"{YooAssetSettings.UnityShadersBundleName}.{Setting.BundleFileVariant}";
|
||||
shareBundleName = $"{YooAssetSettings.UnityShadersBundleName}.{Setting.AssetBundleFileVariant}";
|
||||
return shareBundleName.ToLower();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,5 +98,8 @@ QQ群:**963240451**
|
|||
|
||||
## 友情链接
|
||||
[ET Framework](https://github.com/wqaetly/ET/tree/et7_fgui_yooasset_luban_huatuo): ET 7.0 + FGUI + luban + huatuo + YooAsset + NKGMoba + UniTask,并提供常用的编辑器工具。
|
||||
|
||||
[ETPro](https://github.com/526077247/ETPro) ET6+YooAsset+HybridCLR
|
||||
|
||||
[YooAssetEx](https://gitee.com/liu_zhongxiu/yoo-asset-ex/tree/master): YooAsset Odin扩展工具,用于支持Unity2017和Unity2018版本。
|
||||
|
||||
|
|
Loading…
Reference in New Issue