mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
TEngine 6
This commit is contained in:
@@ -3,4 +3,5 @@
|
||||
[assembly: InternalsVisibleTo("YooAsset.Editor")]
|
||||
[assembly: InternalsVisibleTo("YooAsset.EditorExtension")]
|
||||
[assembly: InternalsVisibleTo("YooAsset.RuntimeExtension")]
|
||||
[assembly: InternalsVisibleTo("YooAsset.Test.Editor")]
|
||||
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]
|
@@ -1,19 +0,0 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public class CacheFileInfo
|
||||
{
|
||||
public string RemoteFileName { private set; get; }
|
||||
public string FilePath { private set; get; }
|
||||
public string FileCRC { private set; get; }
|
||||
public long FileSize { private set; get; }
|
||||
|
||||
public CacheFileInfo(string remoteFileName, string filePath, string fileCRC, long fileSize)
|
||||
{
|
||||
RemoteFileName = remoteFileName;
|
||||
FilePath = filePath;
|
||||
FileCRC = fileCRC;
|
||||
FileSize = fileSize;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,132 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal static class CacheHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 禁用Unity缓存系统在WebGL平台
|
||||
/// </summary>
|
||||
public static bool DisableUnityCacheOnWebGL = false;
|
||||
|
||||
#region 资源信息文件相关
|
||||
private static readonly BufferWriter SharedBuffer = new BufferWriter(1024);
|
||||
|
||||
/// <summary>
|
||||
/// 写入资源包信息
|
||||
/// </summary>
|
||||
public static void WriteInfoToFile(string filePath, string dataFileCRC, long dataFileSize)
|
||||
{
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
SharedBuffer.Clear();
|
||||
SharedBuffer.WriteUTF8(dataFileCRC);
|
||||
SharedBuffer.WriteInt64(dataFileSize);
|
||||
SharedBuffer.WriteToStream(fs);
|
||||
fs.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取资源包信息
|
||||
/// </summary>
|
||||
public static void ReadInfoFromFile(string filePath, out string dataFileCRC, out long dataFileSize)
|
||||
{
|
||||
byte[] binaryData = FileUtility.ReadAllBytes(filePath);
|
||||
BufferReader buffer = new BufferReader(binaryData);
|
||||
dataFileCRC = buffer.ReadUTF8();
|
||||
dataFileSize = buffer.ReadInt64();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 资源文件验证相关
|
||||
/// <summary>
|
||||
/// 验证缓存文件(子线程内操作)
|
||||
/// </summary>
|
||||
public static EVerifyResult VerifyingCacheFile(VerifyCacheFileElement element, EVerifyLevel verifyLevel)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (verifyLevel == EVerifyLevel.Low)
|
||||
{
|
||||
if (File.Exists(element.InfoFilePath) == false)
|
||||
return EVerifyResult.InfoFileNotExisted;
|
||||
if (File.Exists(element.DataFilePath) == false)
|
||||
return EVerifyResult.DataFileNotExisted;
|
||||
return EVerifyResult.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (File.Exists(element.InfoFilePath) == false)
|
||||
return EVerifyResult.InfoFileNotExisted;
|
||||
|
||||
// 解析信息文件获取验证数据
|
||||
CacheHelper.ReadInfoFromFile(element.InfoFilePath, out element.DataFileCRC, out element.DataFileSize);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return EVerifyResult.Exception;
|
||||
}
|
||||
|
||||
return VerifyingInternal(element.DataFilePath, element.DataFileSize, element.DataFileCRC, verifyLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证下载文件(子线程内操作)
|
||||
/// </summary>
|
||||
public static EVerifyResult VerifyingTempFile(VerifyTempFileElement element)
|
||||
{
|
||||
return VerifyingInternal(element.TempDataFilePath, element.FileSize, element.FileCRC, EVerifyLevel.High);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证记录文件(主线程内操作)
|
||||
/// </summary>
|
||||
public static EVerifyResult VerifyingRecordFile(CacheManager cache, string cacheGUID)
|
||||
{
|
||||
var wrapper = cache.TryGetWrapper(cacheGUID);
|
||||
if (wrapper == null)
|
||||
return EVerifyResult.CacheNotFound;
|
||||
|
||||
EVerifyResult result = VerifyingInternal(wrapper.DataFilePath, wrapper.DataFileSize, wrapper.DataFileCRC, EVerifyLevel.High);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EVerifyResult VerifyingInternal(string filePath, long fileSize, string fileCRC, EVerifyLevel verifyLevel)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(filePath) == false)
|
||||
return EVerifyResult.DataFileNotExisted;
|
||||
|
||||
// 先验证文件大小
|
||||
long size = FileUtility.GetFileSize(filePath);
|
||||
if (size < fileSize)
|
||||
return EVerifyResult.FileNotComplete;
|
||||
else if (size > fileSize)
|
||||
return EVerifyResult.FileOverflow;
|
||||
|
||||
// 再验证文件CRC
|
||||
if (verifyLevel == EVerifyLevel.High)
|
||||
{
|
||||
string crc = HashUtility.FileCRC32Safely(filePath);
|
||||
if (crc == fileCRC)
|
||||
return EVerifyResult.Succeed;
|
||||
else
|
||||
return EVerifyResult.FileCrcError;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EVerifyResult.Succeed;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return EVerifyResult.Exception;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -1,136 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class CacheManager
|
||||
{
|
||||
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 readonly string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 验证级别
|
||||
/// </summary>
|
||||
public readonly EVerifyLevel BootVerifyLevel;
|
||||
|
||||
|
||||
public CacheManager(string packageName, EVerifyLevel bootVerifyLevel)
|
||||
{
|
||||
PackageName = packageName;
|
||||
BootVerifyLevel = bootVerifyLevel;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
var wrapper = TryGetWrapper(cacheGUID);
|
||||
if (wrapper != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
string dataFilePath = wrapper.DataFilePath;
|
||||
FileInfo fileInfo = new FileInfo(dataFilePath);
|
||||
if (fileInfo.Exists)
|
||||
fileInfo.Directory.Delete(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
YooLogger.Error($"Failed to delete cache file ! {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存文件总数
|
||||
/// </summary>
|
||||
public int GetAllCachedFilesCount()
|
||||
{
|
||||
return _wrappers.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存GUID集合
|
||||
/// </summary>
|
||||
public List<string> GetAllCachedGUIDs()
|
||||
{
|
||||
List<string> keys = new List<string>(_wrappers.Keys.Count);
|
||||
var keyCollection = _wrappers.Keys;
|
||||
foreach (var key in keyCollection)
|
||||
{
|
||||
keys.Add(key);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65584a0568d40b14582a3c4aaf947b98
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4eb0b0eafee709d478ab6d81faacb304
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,87 +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 ResourcePackage _package;
|
||||
private readonly CacheManager _cache;
|
||||
private List<string> _unusedCacheGUIDs;
|
||||
private int _unusedFileTotalCount = 0;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal ClearUnusedCacheFilesOperation(ResourcePackage package, CacheManager cache)
|
||||
{
|
||||
_package = package;
|
||||
_cache = cache;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.GetUnusedCacheFiles;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.GetUnusedCacheFiles)
|
||||
{
|
||||
_unusedCacheGUIDs = GetUnusedCacheGUIDs();
|
||||
_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];
|
||||
_cache.Discard(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetUnusedCacheGUIDs()
|
||||
{
|
||||
var allCacheGUIDs = _cache.GetAllCachedGUIDs();
|
||||
List<string> result = new List<string>(allCacheGUIDs.Count);
|
||||
foreach (var cacheGUID in allCacheGUIDs)
|
||||
{
|
||||
if (_package.IsIncludeBundleFile(cacheGUID) == false)
|
||||
{
|
||||
result.Add(cacheGUID);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d188c50fd00bf941b2eeebb374dc0d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,99 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public class GetAllCacheFileInfosOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
TryLoadCacheManifest,
|
||||
GetCacheFileInfos,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly PersistentManager _persistent;
|
||||
private readonly CacheManager _cache;
|
||||
private readonly string _packageVersion;
|
||||
private LoadCacheManifestOperation _tryLoadCacheManifestOp;
|
||||
private PackageManifest _manifest;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
private List<CacheFileInfo> _cacheFileInfos;
|
||||
|
||||
/// <summary>
|
||||
/// 搜索结果
|
||||
/// </summary>
|
||||
public List<CacheFileInfo> Result
|
||||
{
|
||||
get { return _cacheFileInfos; }
|
||||
}
|
||||
|
||||
|
||||
internal GetAllCacheFileInfosOperation(PersistentManager persistent, CacheManager cache, string packageVersion)
|
||||
{
|
||||
_persistent = persistent;
|
||||
_cache = cache;
|
||||
_packageVersion = packageVersion;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.TryLoadCacheManifest;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.TryLoadCacheManifest)
|
||||
{
|
||||
if (_tryLoadCacheManifestOp == null)
|
||||
{
|
||||
_tryLoadCacheManifestOp = new LoadCacheManifestOperation(_persistent, _packageVersion);
|
||||
OperationSystem.StartOperation(_cache.PackageName, _tryLoadCacheManifestOp);
|
||||
}
|
||||
|
||||
if (_tryLoadCacheManifestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_tryLoadCacheManifestOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_manifest = _tryLoadCacheManifestOp.Manifest;
|
||||
_steps = ESteps.GetCacheFileInfos;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _tryLoadCacheManifestOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.GetCacheFileInfos)
|
||||
{
|
||||
var allCachedGUIDs = _cache.GetAllCachedGUIDs();
|
||||
_cacheFileInfos = new List<CacheFileInfo>(allCachedGUIDs.Count);
|
||||
for (int i = 0; i < allCachedGUIDs.Count; i++)
|
||||
{
|
||||
var cachedGUID = allCachedGUIDs[i];
|
||||
var wrapper = _cache.TryGetWrapper(cachedGUID);
|
||||
if (wrapper != null)
|
||||
{
|
||||
if (_manifest.TryGetPackageBundleByCacheGUID(cachedGUID, out var packageBundle))
|
||||
{
|
||||
var cacheFileInfo = new CacheFileInfo(packageBundle.FileName, wrapper.DataFilePath, wrapper.DataFileCRC, wrapper.DataFileSize);
|
||||
_cacheFileInfos.Add(cacheFileInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 注意:总是返回成功
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d37e37f5d78ddf8468adcf2dff1edfbb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00ec004354d75ac499606d6959192f9b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,254 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class VerifyCacheFilesOperation : AsyncOperationBase
|
||||
{
|
||||
public static VerifyCacheFilesOperation CreateOperation(CacheManager cache, List<VerifyCacheFileElement> elements)
|
||||
{
|
||||
#if UNITY_WEBGL
|
||||
var operation = new VerifyCacheFilesWithoutThreadOperation(cache, elements);
|
||||
#else
|
||||
var operation = new VerifyCacheFilesWithThreadOperation(cache, elements);
|
||||
#endif
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地缓存文件验证(线程版)
|
||||
/// </summary>
|
||||
internal class VerifyCacheFilesWithThreadOperation : VerifyCacheFilesOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
InitVerify,
|
||||
UpdateVerify,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly ThreadSyncContext _syncContext = new ThreadSyncContext();
|
||||
private readonly CacheManager _cache;
|
||||
private List<VerifyCacheFileElement> _waitingList;
|
||||
private List<VerifyCacheFileElement> _verifyingList;
|
||||
private int _verifyMaxNum;
|
||||
private int _verifyTotalCount;
|
||||
private float _verifyStartTime;
|
||||
private int _succeedCount;
|
||||
private int _failedCount;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public VerifyCacheFilesWithThreadOperation(CacheManager cache, List<VerifyCacheFileElement> elements)
|
||||
{
|
||||
_cache = cache;
|
||||
_waitingList = elements;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.InitVerify;
|
||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
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<VerifyCacheFileElement>(_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($"Verify cache files 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(VerifyCacheFileElement element)
|
||||
{
|
||||
return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), element);
|
||||
}
|
||||
private void VerifyInThread(object obj)
|
||||
{
|
||||
VerifyCacheFileElement element = (VerifyCacheFileElement)obj;
|
||||
element.Result = CacheHelper.VerifyingCacheFile(element, _cache.BootVerifyLevel);
|
||||
_syncContext.Post(VerifyCallback, element);
|
||||
}
|
||||
private void VerifyCallback(object obj)
|
||||
{
|
||||
VerifyCacheFileElement element = (VerifyCacheFileElement)obj;
|
||||
_verifyingList.Remove(element);
|
||||
|
||||
if (element.Result == EVerifyResult.Succeed)
|
||||
{
|
||||
_succeedCount++;
|
||||
var wrapper = new CacheManager.RecordWrapper(element.InfoFilePath, element.DataFilePath, element.DataFileCRC, element.DataFileSize);
|
||||
_cache.Record(element.CacheGUID, wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
_failedCount++;
|
||||
|
||||
YooLogger.Warning($"Failed verify file and delete files : {element.FileRootPath}");
|
||||
element.DeleteFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地缓存文件验证(非线程版)
|
||||
/// </summary>
|
||||
internal class VerifyCacheFilesWithoutThreadOperation : VerifyCacheFilesOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
InitVerify,
|
||||
UpdateVerify,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly CacheManager _cache;
|
||||
private List<VerifyCacheFileElement> _waitingList;
|
||||
private List<VerifyCacheFileElement> _verifyingList;
|
||||
private int _verifyMaxNum;
|
||||
private int _verifyTotalCount;
|
||||
private float _verifyStartTime;
|
||||
private int _succeedCount;
|
||||
private int _failedCount;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public VerifyCacheFilesWithoutThreadOperation(CacheManager cache, List<VerifyCacheFileElement> elements)
|
||||
{
|
||||
_cache = cache;
|
||||
_waitingList = elements;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.InitVerify;
|
||||
_verifyStartTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.InitVerify)
|
||||
{
|
||||
int fileCount = _waitingList.Count;
|
||||
|
||||
// 设置同时验证的最大数
|
||||
_verifyMaxNum = fileCount;
|
||||
_verifyTotalCount = fileCount;
|
||||
|
||||
_verifyingList = new List<VerifyCacheFileElement>(_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(VerifyCacheFileElement element)
|
||||
{
|
||||
element.Result = CacheHelper.VerifyingCacheFile(element, _cache.BootVerifyLevel);
|
||||
if (element.Result == EVerifyResult.Succeed)
|
||||
{
|
||||
_succeedCount++;
|
||||
var wrapper = new CacheManager.RecordWrapper(element.InfoFilePath, element.DataFilePath, element.DataFileCRC, element.DataFileSize);
|
||||
_cache.Record(element.CacheGUID, wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
_failedCount++;
|
||||
|
||||
YooLogger.Warning($"Failed verify file and delete files : {element.FileRootPath}");
|
||||
element.DeleteFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,141 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class VerifyTempFileOperation : AsyncOperationBase
|
||||
{
|
||||
public EVerifyResult VerifyResult { protected set; get; }
|
||||
|
||||
public static VerifyTempFileOperation CreateOperation(VerifyTempFileElement element)
|
||||
{
|
||||
#if UNITY_WEBGL
|
||||
var operation = new VerifyTempFileWithoutThreadOperation(element);
|
||||
#else
|
||||
var operation = new VerifyTempFileWithThreadOperation(element);
|
||||
#endif
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载文件验证(线程版)
|
||||
/// </summary>
|
||||
internal class VerifyTempFileWithThreadOperation : VerifyTempFileOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
VerifyFile,
|
||||
Waiting,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly VerifyTempFileElement _element;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public VerifyTempFileWithThreadOperation(VerifyTempFileElement element)
|
||||
{
|
||||
_element = element;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.VerifyFile;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.VerifyFile)
|
||||
{
|
||||
if (BeginVerifyFileWithThread(_element))
|
||||
{
|
||||
_steps = ESteps.Waiting;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Waiting)
|
||||
{
|
||||
int result = _element.Result;
|
||||
if (result == 0)
|
||||
return;
|
||||
|
||||
VerifyResult = (EVerifyResult)result;
|
||||
if (VerifyResult == EVerifyResult.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed verify file : {_element.TempDataFilePath} ! ErrorCode : {VerifyResult}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool BeginVerifyFileWithThread(VerifyTempFileElement element)
|
||||
{
|
||||
return ThreadPool.QueueUserWorkItem(new WaitCallback(VerifyInThread), element);
|
||||
}
|
||||
private void VerifyInThread(object obj)
|
||||
{
|
||||
VerifyTempFileElement element = (VerifyTempFileElement)obj;
|
||||
int result = (int)CacheHelper.VerifyingTempFile(element);
|
||||
element.Result = result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载文件验证(非线程版)
|
||||
/// </summary>
|
||||
internal class VerifyTempFileWithoutThreadOperation : VerifyTempFileOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
VerifyFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly VerifyTempFileElement _element;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public VerifyTempFileWithoutThreadOperation(VerifyTempFileElement element)
|
||||
{
|
||||
_element = element;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.VerifyFile;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.VerifyFile)
|
||||
{
|
||||
_element.Result = (int)CacheHelper.VerifyingTempFile(_element);
|
||||
|
||||
VerifyResult = (EVerifyResult)_element.Result;
|
||||
if (VerifyResult == EVerifyResult.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Failed verify file : {_element.TempDataFilePath} ! ErrorCode : {VerifyResult}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,74 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class PackageCachingOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
FindCacheFiles,
|
||||
VerifyCacheFiles,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly PersistentManager _persistent;
|
||||
private readonly CacheManager _cache;
|
||||
private FindCacheFilesOperation _findCacheFilesOp;
|
||||
private VerifyCacheFilesOperation _verifyCacheFilesOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public PackageCachingOperation(PersistentManager persistent, CacheManager cache)
|
||||
{
|
||||
_persistent = persistent;
|
||||
_cache = cache;
|
||||
}
|
||||
internal override void InternalOnStart()
|
||||
{
|
||||
_steps = ESteps.FindCacheFiles;
|
||||
}
|
||||
internal override void InternalOnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.FindCacheFiles)
|
||||
{
|
||||
if (_findCacheFilesOp == null)
|
||||
{
|
||||
_findCacheFilesOp = new FindCacheFilesOperation(_persistent, _cache);
|
||||
OperationSystem.StartOperation(_cache.PackageName, _findCacheFilesOp);
|
||||
}
|
||||
|
||||
Progress = _findCacheFilesOp.Progress;
|
||||
if (_findCacheFilesOp.IsDone == false)
|
||||
return;
|
||||
|
||||
_steps = ESteps.VerifyCacheFiles;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.VerifyCacheFiles)
|
||||
{
|
||||
if (_verifyCacheFilesOp == null)
|
||||
{
|
||||
_verifyCacheFilesOp = VerifyCacheFilesOperation.CreateOperation(_cache, _findCacheFilesOp.VerifyElements);
|
||||
OperationSystem.StartOperation(_cache.PackageName, _verifyCacheFilesOp);
|
||||
}
|
||||
|
||||
Progress = _verifyCacheFilesOp.Progress;
|
||||
if (_verifyCacheFilesOp.IsDone == false)
|
||||
return;
|
||||
|
||||
// 注意:总是返回成功
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
|
||||
int totalCount = _cache.GetAllCachedFilesCount();
|
||||
YooLogger.Log($"Package '{_cache.PackageName}' cached files count : {totalCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ff95e7516dbfa148b4fe16eaab783fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,33 +0,0 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal static class PersistentHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取WWW加载本地资源的路径
|
||||
/// </summary>
|
||||
public static string ConvertToWWWPath(string path)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return StringUtility.Format("file:///{0}", path);
|
||||
#elif UNITY_WEBGL
|
||||
return path;
|
||||
#elif UNITY_IPHONE
|
||||
return StringUtility.Format("file://{0}", path);
|
||||
#elif UNITY_ANDROID
|
||||
if (path.StartsWith("jar:file://"))
|
||||
return path;
|
||||
else
|
||||
return StringUtility.Format("jar:file://{0}", path);
|
||||
#elif UNITY_STANDALONE_OSX
|
||||
return new System.Uri(path).ToString();
|
||||
#elif UNITY_STANDALONE
|
||||
return StringUtility.Format("file:///{0}", path);
|
||||
#elif UNITY_OPENHARMONY
|
||||
return path;
|
||||
#else
|
||||
return path;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9581e7c53fe081749ab849ec6e2be3d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,217 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class PersistentManager
|
||||
{
|
||||
private readonly Dictionary<string, string> _cachedDataFilePaths = new Dictionary<string, string>(10000);
|
||||
private readonly Dictionary<string, string> _cachedInfoFilePaths = new Dictionary<string, string>(10000);
|
||||
private readonly Dictionary<string, string> _tempDataFilePaths = new Dictionary<string, string>(10000);
|
||||
private readonly Dictionary<string, string> _buildinFilePaths = new Dictionary<string, string>(10000);
|
||||
|
||||
/// <summary>
|
||||
/// 所属包裹
|
||||
/// </summary>
|
||||
public readonly string PackageName;
|
||||
|
||||
public string BuildinRoot { private set; get; }
|
||||
public string BuildinPackageRoot { private set; get; }
|
||||
|
||||
public string SandboxRoot { private set; get; }
|
||||
public string SandboxPackageRoot { private set; get; }
|
||||
public string SandboxCacheFilesRoot { private set; get; }
|
||||
public string SandboxManifestFilesRoot { private set; get; }
|
||||
public string SandboxAppFootPrintFilePath { private set; get; }
|
||||
|
||||
public bool AppendFileExtension { private set; get; }
|
||||
|
||||
|
||||
public PersistentManager(string packageName)
|
||||
{
|
||||
PackageName = packageName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化
|
||||
/// </summary>
|
||||
public void Initialize(string buildinRoot, string sandboxRoot, bool appendFileExtension)
|
||||
{
|
||||
if (string.IsNullOrEmpty(buildinRoot))
|
||||
BuildinRoot = CreateDefaultBuildinRoot();
|
||||
else
|
||||
BuildinRoot = buildinRoot;
|
||||
|
||||
if (string.IsNullOrEmpty(sandboxRoot))
|
||||
SandboxRoot = CreateDefaultSandboxRoot();
|
||||
else
|
||||
SandboxRoot = sandboxRoot;
|
||||
|
||||
BuildinPackageRoot = PathUtility.Combine(BuildinRoot, PackageName);
|
||||
SandboxPackageRoot = PathUtility.Combine(SandboxRoot, PackageName);
|
||||
SandboxCacheFilesRoot = PathUtility.Combine(SandboxPackageRoot, YooAssetSettings.CacheFilesFolderName);
|
||||
SandboxManifestFilesRoot = PathUtility.Combine(SandboxPackageRoot, YooAssetSettings.ManifestFolderName);
|
||||
SandboxAppFootPrintFilePath = PathUtility.Combine(SandboxPackageRoot, YooAssetSettings.AppFootPrintFileName);
|
||||
AppendFileExtension = appendFileExtension;
|
||||
}
|
||||
private static string CreateDefaultBuildinRoot()
|
||||
{
|
||||
string path = PathUtility.Combine(UnityEngine.Application.streamingAssetsPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
||||
#if UNITY_OPENHARMONY
|
||||
return $"file://{path}";
|
||||
#else
|
||||
return path;
|
||||
#endif
|
||||
}
|
||||
private static string CreateDefaultSandboxRoot()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// 注意:为了方便调试查看,编辑器下把存储目录放到项目里。
|
||||
string projectPath = Path.GetDirectoryName(UnityEngine.Application.dataPath);
|
||||
projectPath = PathUtility.RegularPath(projectPath);
|
||||
return PathUtility.Combine(projectPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
||||
#elif UNITY_STANDALONE
|
||||
return PathUtility.Combine(UnityEngine.Application.dataPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
||||
#else
|
||||
return PathUtility.Combine(UnityEngine.Application.persistentDataPath, YooAssetSettingsData.Setting.DefaultYooFolderName);
|
||||
#endif
|
||||
}
|
||||
|
||||
public string GetCachedDataFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_cachedDataFilePaths.TryGetValue(bundle.CacheGUID, out string filePath) == false)
|
||||
{
|
||||
string folderName = bundle.FileHash.Substring(0, 2);
|
||||
filePath = PathUtility.Combine(SandboxCacheFilesRoot, folderName, bundle.CacheGUID, YooAssetSettings.CacheBundleDataFileName);
|
||||
if (AppendFileExtension)
|
||||
filePath += bundle.FileExtension;
|
||||
_cachedDataFilePaths.Add(bundle.CacheGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
public string GetCachedInfoFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_cachedInfoFilePaths.TryGetValue(bundle.CacheGUID, out string filePath) == false)
|
||||
{
|
||||
string folderName = bundle.FileHash.Substring(0, 2);
|
||||
filePath = PathUtility.Combine(SandboxCacheFilesRoot, folderName, bundle.CacheGUID, YooAssetSettings.CacheBundleInfoFileName);
|
||||
_cachedInfoFilePaths.Add(bundle.CacheGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
public string GetTempDataFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_tempDataFilePaths.TryGetValue(bundle.CacheGUID, out string filePath) == false)
|
||||
{
|
||||
string cachedDataFilePath = GetCachedDataFilePath(bundle);
|
||||
filePath = $"{cachedDataFilePath}.temp";
|
||||
_tempDataFilePaths.Add(bundle.CacheGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
public string GetBuildinFilePath(PackageBundle bundle)
|
||||
{
|
||||
if (_buildinFilePaths.TryGetValue(bundle.CacheGUID, out string filePath) == false)
|
||||
{
|
||||
filePath = PathUtility.Combine(BuildinPackageRoot, bundle.FileName);
|
||||
_buildinFilePaths.Add(bundle.CacheGUID, filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除沙盒里的包裹目录
|
||||
/// </summary>
|
||||
public void DeleteSandboxPackageFolder()
|
||||
{
|
||||
if (Directory.Exists(SandboxPackageRoot))
|
||||
Directory.Delete(SandboxPackageRoot, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除沙盒内的缓存文件夹
|
||||
/// </summary>
|
||||
public void DeleteSandboxCacheFilesFolder()
|
||||
{
|
||||
if (Directory.Exists(SandboxCacheFilesRoot))
|
||||
Directory.Delete(SandboxCacheFilesRoot, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除沙盒内的清单文件夹
|
||||
/// </summary>
|
||||
public void DeleteSandboxManifestFilesFolder()
|
||||
{
|
||||
if (Directory.Exists(SandboxManifestFilesRoot))
|
||||
Directory.Delete(SandboxManifestFilesRoot, true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取沙盒内包裹的清单文件的路径
|
||||
/// </summary>
|
||||
public string GetSandboxPackageManifestFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(SandboxManifestFilesRoot, fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取沙盒内包裹的哈希文件的路径
|
||||
/// </summary>
|
||||
public string GetSandboxPackageHashFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(SandboxManifestFilesRoot, fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取沙盒内包裹的版本文件的路径
|
||||
/// </summary>
|
||||
public string GetSandboxPackageVersionFilePath()
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
|
||||
return PathUtility.Combine(SandboxManifestFilesRoot, fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存沙盒内默认的包裹版本
|
||||
/// </summary>
|
||||
public void SaveSandboxPackageVersionFile(string version)
|
||||
{
|
||||
YooLogger.Log($"Save package version : {version}");
|
||||
string filePath = GetSandboxPackageVersionFilePath();
|
||||
FileUtility.WriteAllText(filePath, version);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取APP内包裹的清单文件的路径
|
||||
/// </summary>
|
||||
public string GetBuildinPackageManifestFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(BuildinPackageRoot, fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取APP内包裹的哈希文件的路径
|
||||
/// </summary>
|
||||
public string GetBuildinPackageHashFilePath(string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(PackageName, packageVersion);
|
||||
return PathUtility.Combine(BuildinPackageRoot, fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取APP内包裹的版本文件的路径
|
||||
/// </summary>
|
||||
public string GetBuildinPackageVersionFilePath()
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(PackageName);
|
||||
return PathUtility.Combine(BuildinPackageRoot, fileName);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62ee5fd2821fe85488efff3f8242b703
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,60 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存文件验证元素
|
||||
/// </summary>
|
||||
internal class VerifyCacheFileElement
|
||||
{
|
||||
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 VerifyCacheFileElement(string packageName, string cacheGUID, string fileRootPath, string dataFilePath, string infoFilePath)
|
||||
{
|
||||
PackageName = packageName;
|
||||
CacheGUID = cacheGUID;
|
||||
FileRootPath = fileRootPath;
|
||||
DataFilePath = dataFilePath;
|
||||
InfoFilePath = infoFilePath;
|
||||
}
|
||||
|
||||
public void DeleteFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(FileRootPath, true);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
YooLogger.Warning($"Failed delete cache bundle folder : {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载文件验证元素
|
||||
/// </summary>
|
||||
internal class VerifyTempFileElement
|
||||
{
|
||||
public string TempDataFilePath { private set; get; }
|
||||
public string FileCRC { private set; get; }
|
||||
public long FileSize { private set; get; }
|
||||
|
||||
public int Result = 0; // 注意:原子操作对象
|
||||
|
||||
public VerifyTempFileElement(string tempDataFilePath, string fileCRC, long fileSize)
|
||||
{
|
||||
TempDataFilePath = tempDataFilePath;
|
||||
FileCRC = fileCRC;
|
||||
FileSize = fileSize;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a4b96484bd701f4289b2f74c38abaa8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -5,13 +5,8 @@ using System.Collections.Generic;
|
||||
namespace YooAsset
|
||||
{
|
||||
[Serializable]
|
||||
internal class DebugBundleInfo : IComparer<DebugBundleInfo>, IComparable<DebugBundleInfo>
|
||||
internal struct DebugBundleInfo : IComparer<DebugBundleInfo>, IComparable<DebugBundleInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// 包裹名
|
||||
/// </summary>
|
||||
public string PackageName { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
@@ -27,6 +22,11 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public string Status;
|
||||
|
||||
/// <summary>
|
||||
/// 谁引用了该资源包
|
||||
/// </summary>
|
||||
public List<string> ReferenceBundles;
|
||||
|
||||
public int CompareTo(DebugBundleInfo other)
|
||||
{
|
||||
return Compare(this, other);
|
||||
|
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
[Serializable]
|
||||
internal struct DebugOperationInfo : IComparer<DebugOperationInfo>, IComparable<DebugOperationInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务名称
|
||||
/// </summary>
|
||||
public string OperationName;
|
||||
|
||||
/// <summary>
|
||||
/// 任务说明
|
||||
/// </summary>
|
||||
public string OperationDesc;
|
||||
|
||||
/// <summary>
|
||||
/// 优先级
|
||||
/// </summary>
|
||||
public uint Priority;
|
||||
|
||||
/// <summary>
|
||||
/// 任务进度
|
||||
/// </summary>
|
||||
public float Progress;
|
||||
|
||||
/// <summary>
|
||||
/// 任务开始的时间
|
||||
/// </summary>
|
||||
public string BeginTime;
|
||||
|
||||
/// <summary>
|
||||
/// 处理耗时(单位:毫秒)
|
||||
/// </summary>
|
||||
public long ProcessTime;
|
||||
|
||||
/// <summary>
|
||||
/// 任务状态
|
||||
/// </summary>
|
||||
public string Status;
|
||||
|
||||
/// <summary>
|
||||
/// 子任务列表
|
||||
/// TODO : Serialization depth limit 10 exceeded
|
||||
/// </summary>
|
||||
public List<DebugOperationInfo> Childs;
|
||||
|
||||
public int CompareTo(DebugOperationInfo other)
|
||||
{
|
||||
return Compare(this, other);
|
||||
}
|
||||
public int Compare(DebugOperationInfo a, DebugOperationInfo b)
|
||||
{
|
||||
return string.CompareOrdinal(a.OperationName, b.OperationName);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02ad351eb8539da47a0c789e2f8c468f
|
||||
guid: 942ce6ad7b4427d4d87a8a29c8b9371f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -13,9 +13,42 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 调试数据列表
|
||||
/// </summary>
|
||||
public List<DebugProviderInfo> ProviderInfos = new List<DebugProviderInfo>(1000);
|
||||
public List<DebugBundleInfo> BundleInfos = new List<DebugBundleInfo>(1000);
|
||||
public List<DebugOperationInfo> OperationInfos = new List<DebugOperationInfo>(1000);
|
||||
|
||||
|
||||
[NonSerialized]
|
||||
public Dictionary<string, DebugBundleInfo> BundleInfoDic = new Dictionary<string, DebugBundleInfo>();
|
||||
private bool _isParse = false;
|
||||
|
||||
/// <summary>
|
||||
/// 获取调试资源包信息类
|
||||
/// </summary>
|
||||
public DebugBundleInfo GetBundleInfo(string bundleName)
|
||||
{
|
||||
// 解析数据
|
||||
if (_isParse == false)
|
||||
{
|
||||
_isParse = true;
|
||||
foreach (var bundleInfo in BundleInfos)
|
||||
{
|
||||
if (BundleInfoDic.ContainsKey(bundleInfo.BundleName) == false)
|
||||
{
|
||||
BundleInfoDic.Add(bundleInfo.BundleName, bundleInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BundleInfoDic.TryGetValue(bundleName, out DebugBundleInfo value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Debug.LogError($"Can not found {nameof(DebugBundleInfo)} : {bundleName}");
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,7 +5,7 @@ using System.Collections.Generic;
|
||||
namespace YooAsset
|
||||
{
|
||||
[Serializable]
|
||||
internal class DebugProviderInfo : IComparer<DebugProviderInfo>, IComparable<DebugProviderInfo>
|
||||
internal struct DebugProviderInfo : IComparer<DebugProviderInfo>, IComparable<DebugProviderInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// 包裹名
|
||||
@@ -23,9 +23,9 @@ namespace YooAsset
|
||||
public string SpawnScene;
|
||||
|
||||
/// <summary>
|
||||
/// 资源出生的时间
|
||||
/// 资源加载开始时间
|
||||
/// </summary>
|
||||
public string SpawnTime;
|
||||
public string BeginTime;
|
||||
|
||||
/// <summary>
|
||||
/// 加载耗时(单位:毫秒)
|
||||
@@ -45,7 +45,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 依赖的资源包列表
|
||||
/// </summary>
|
||||
public List<DebugBundleInfo> DependBundleInfos;
|
||||
public List<string> DependBundles;
|
||||
|
||||
public int CompareTo(DebugProviderInfo other)
|
||||
{
|
||||
|
@@ -12,6 +12,11 @@ namespace YooAsset
|
||||
[Serializable]
|
||||
internal class DebugReport
|
||||
{
|
||||
/// <summary>
|
||||
/// 调试器版本
|
||||
/// </summary>
|
||||
public string DebuggerVersion = RemoteDebuggerDefine.DebuggerVersion;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏帧
|
||||
/// </summary>
|
||||
@@ -22,7 +27,6 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public List<DebugPackageData> PackageDatas = new List<DebugPackageData>(10);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 序列化
|
||||
/// </summary>
|
||||
|
@@ -10,6 +10,11 @@ namespace YooAsset
|
||||
/// 采样一次
|
||||
/// </summary>
|
||||
SampleOnce = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 自动采集
|
||||
/// </summary>
|
||||
SampleAuto = 1,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class RemoteDebuggerDefine
|
||||
{
|
||||
public static readonly Guid kMsgSendPlayerToEditor = new Guid("e34a5702dd353724aa315fb8011f08c3");
|
||||
public static readonly Guid kMsgSendEditorToPlayer = new Guid("4d1926c9df5b052469a1c63448b7609a");
|
||||
public const string DebuggerVersion = "2.3.3";
|
||||
public static readonly Guid kMsgPlayerSendToEditor = new Guid("e34a5702dd353724aa315fb8011f08c3");
|
||||
public static readonly Guid kMsgEditorSendToPlayer = new Guid("4d1926c9df5b052469a1c63448b7609a");
|
||||
}
|
||||
}
|
@@ -7,47 +7,66 @@ namespace YooAsset
|
||||
{
|
||||
internal class RemoteDebuggerInRuntime : MonoBehaviour
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// 编辑器下获取报告的回调
|
||||
/// </summary>
|
||||
public static Action<int, DebugReport> EditorHandleDebugReportCallback;
|
||||
private static bool _sampleOnce = false;
|
||||
private static bool _autoSample = false;
|
||||
|
||||
/// <summary>
|
||||
/// 编辑器下请求报告数据
|
||||
/// </summary>
|
||||
public static void EditorRequestDebugReport()
|
||||
private void Awake()
|
||||
{
|
||||
if (UnityEditor.EditorApplication.isPlaying)
|
||||
{
|
||||
var report = YooAssets.GetDebugReport();
|
||||
EditorHandleDebugReportCallback?.Invoke(0, report);
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
RemotePlayerConnection.Instance.Initialize();
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
private void OnEnable()
|
||||
{
|
||||
PlayerConnection.instance.Register(RemoteDebuggerDefine.kMsgSendEditorToPlayer, OnHandleEditorMessage);
|
||||
#if UNITY_EDITOR
|
||||
RemotePlayerConnection.Instance.Register(RemoteDebuggerDefine.kMsgEditorSendToPlayer, OnHandleEditorMessage);
|
||||
#else
|
||||
PlayerConnection.instance.Register(RemoteDebuggerDefine.kMsgEditorSendToPlayer, OnHandleEditorMessage);
|
||||
#endif
|
||||
}
|
||||
private void OnDisable()
|
||||
{
|
||||
PlayerConnection.instance.Unregister(RemoteDebuggerDefine.kMsgSendEditorToPlayer, OnHandleEditorMessage);
|
||||
#if UNITY_EDITOR
|
||||
RemotePlayerConnection.Instance.Unregister(RemoteDebuggerDefine.kMsgEditorSendToPlayer);
|
||||
#else
|
||||
PlayerConnection.instance.Unregister(RemoteDebuggerDefine.kMsgEditorSendToPlayer, OnHandleEditorMessage);
|
||||
#endif
|
||||
}
|
||||
private void OnHandleEditorMessage(MessageEventArgs args)
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (_autoSample || _sampleOnce)
|
||||
{
|
||||
_sampleOnce = false;
|
||||
var debugReport = YooAssets.GetDebugReport();
|
||||
var data = DebugReport.Serialize(debugReport);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
RemotePlayerConnection.Instance.Send(RemoteDebuggerDefine.kMsgPlayerSendToEditor, data);
|
||||
#else
|
||||
PlayerConnection.instance.Send(RemoteDebuggerDefine.kMsgPlayerSendToEditor, data);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnHandleEditorMessage(MessageEventArgs args)
|
||||
{
|
||||
var command = RemoteCommand.Deserialize(args.data);
|
||||
YooLogger.Log($"On handle remote command : {command.CommandType} Param : {command.CommandParam}");
|
||||
if (command.CommandType == (int)ERemoteCommand.SampleOnce)
|
||||
{
|
||||
var debugReport = YooAssets.GetDebugReport();
|
||||
var data = DebugReport.Serialize(debugReport);
|
||||
PlayerConnection.instance.Send(RemoteDebuggerDefine.kMsgSendPlayerToEditor, data);
|
||||
_sampleOnce = true;
|
||||
}
|
||||
else if (command.CommandType == (int)ERemoteCommand.SampleAuto)
|
||||
{
|
||||
if (command.CommandParam == "open")
|
||||
_autoSample = true;
|
||||
else
|
||||
_autoSample = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(command.CommandType.ToString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Networking.PlayerConnection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class RemoteEditorConnection
|
||||
{
|
||||
private static RemoteEditorConnection _instance;
|
||||
public static RemoteEditorConnection Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
_instance = new RemoteEditorConnection();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<Guid, UnityAction<MessageEventArgs>> _messageCallbacks = new Dictionary<Guid, UnityAction<MessageEventArgs>>();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_messageCallbacks.Clear();
|
||||
}
|
||||
public void Register(Guid messageID, UnityAction<MessageEventArgs> callback)
|
||||
{
|
||||
if (messageID == Guid.Empty)
|
||||
throw new ArgumentException("messageID is empty !");
|
||||
|
||||
if (_messageCallbacks.ContainsKey(messageID) == false)
|
||||
_messageCallbacks.Add(messageID, callback);
|
||||
}
|
||||
public void Unregister(Guid messageID)
|
||||
{
|
||||
if (_messageCallbacks.ContainsKey(messageID))
|
||||
_messageCallbacks.Remove(messageID);
|
||||
}
|
||||
public void Send(Guid messageID, byte[] data)
|
||||
{
|
||||
if (messageID == Guid.Empty)
|
||||
throw new ArgumentException("messageID is empty !");
|
||||
|
||||
// 接收对方的消息
|
||||
RemotePlayerConnection.Instance.HandleEditorMessage(messageID, data);
|
||||
}
|
||||
|
||||
internal void HandlePlayerMessage(Guid messageID, byte[] data)
|
||||
{
|
||||
if (_messageCallbacks.TryGetValue(messageID, out UnityAction<MessageEventArgs> value))
|
||||
{
|
||||
var args = new MessageEventArgs();
|
||||
args.playerId = 0;
|
||||
args.data = data;
|
||||
value?.Invoke(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8616c7550a7890141af598898a12df1b
|
||||
guid: 557f37a710d7e2c4d80fe0f778d66463
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Networking.PlayerConnection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class RemotePlayerConnection
|
||||
{
|
||||
private static RemotePlayerConnection _instance;
|
||||
public static RemotePlayerConnection Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
_instance = new RemotePlayerConnection();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<Guid, UnityAction<MessageEventArgs>> _messageCallbacks = new Dictionary<Guid, UnityAction<MessageEventArgs>>();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_messageCallbacks.Clear();
|
||||
}
|
||||
public void Register(Guid messageID, UnityAction<MessageEventArgs> callback)
|
||||
{
|
||||
if (messageID == Guid.Empty)
|
||||
throw new ArgumentException("messageID is empty !");
|
||||
|
||||
if (_messageCallbacks.ContainsKey(messageID) == false)
|
||||
_messageCallbacks.Add(messageID, callback);
|
||||
}
|
||||
public void Unregister(Guid messageID)
|
||||
{
|
||||
if (_messageCallbacks.ContainsKey(messageID))
|
||||
_messageCallbacks.Remove(messageID);
|
||||
}
|
||||
public void Send(Guid messageID, byte[] data)
|
||||
{
|
||||
if (messageID == Guid.Empty)
|
||||
throw new ArgumentException("messageID is empty !");
|
||||
|
||||
// 接收对方的消息
|
||||
RemoteEditorConnection.Instance.HandlePlayerMessage(messageID, data);
|
||||
}
|
||||
|
||||
internal void HandleEditorMessage(Guid messageID, byte[] data)
|
||||
{
|
||||
if (_messageCallbacks.TryGetValue(messageID, out UnityAction<MessageEventArgs> value))
|
||||
{
|
||||
var args = new MessageEventArgs();
|
||||
args.playerId = 0;
|
||||
args.data = data;
|
||||
value?.Invoke(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4a97c06e069c1146a881fcb359f9b4b
|
||||
guid: 0a726a61cbc448749a4ee80b8c9860b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -0,0 +1,97 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载器结束
|
||||
/// </summary>
|
||||
public struct DownloaderFinishData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
public bool Succeed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的更新数据
|
||||
/// </summary>
|
||||
public struct DownloadUpdateData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度 (0-1f)
|
||||
/// </summary>
|
||||
public float Progress;
|
||||
|
||||
/// <summary>
|
||||
/// 下载文件总数
|
||||
/// </summary>
|
||||
public int TotalDownloadCount;
|
||||
|
||||
/// <summary>
|
||||
/// 当前完成的下载文件数量
|
||||
/// </summary>
|
||||
public int CurrentDownloadCount;
|
||||
|
||||
/// <summary>
|
||||
/// 下载数据总大小(单位:字节)
|
||||
/// </summary>
|
||||
public long TotalDownloadBytes;
|
||||
|
||||
/// <summary>
|
||||
/// 当前完成的下载数据大小(单位:字节)
|
||||
/// </summary>
|
||||
public long CurrentDownloadBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的错误数据
|
||||
/// </summary>
|
||||
public struct DownloadErrorData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载失败的文件名称
|
||||
/// </summary>
|
||||
public string FileName;
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string ErrorInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载器相关的文件数据
|
||||
/// </summary>
|
||||
public struct DownloadFileData
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属包裹名称
|
||||
/// </summary>
|
||||
public string PackageName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载的文件名称
|
||||
/// </summary>
|
||||
public string FileName;
|
||||
|
||||
/// <summary>
|
||||
/// 下载的文件大小
|
||||
/// </summary>
|
||||
public long FileSize;
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08f3e92fdbd5d56459d8882be1f54f60
|
||||
guid: 6602c4be2ef295546b7bbb328de8fb0c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -1,41 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 自定义下载器的请求委托
|
||||
/// </summary>
|
||||
public delegate UnityWebRequest DownloadRequestDelegate(string url);
|
||||
|
||||
|
||||
internal static class DownloadHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载失败后清理文件的HTTP错误码
|
||||
/// </summary>
|
||||
public static List<long> ClearFileResponseCodes { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义下载器的请求委托
|
||||
/// </summary>
|
||||
public static DownloadRequestDelegate RequestDelegate = null;
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的网络请求
|
||||
/// </summary>
|
||||
public static UnityWebRequest NewRequest(string requestURL)
|
||||
{
|
||||
UnityWebRequest webRequest;
|
||||
if (RequestDelegate != null)
|
||||
webRequest = RequestDelegate.Invoke(requestURL);
|
||||
else
|
||||
webRequest = new UnityWebRequest(requestURL, UnityWebRequest.kHttpVerbGET);
|
||||
return webRequest;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d19eae1f43ecf6347925a06730a6c846
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,150 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 1. 保证每一时刻资源文件只存在一个下载器
|
||||
/// 2. 保证下载器下载完成后立刻验证并缓存
|
||||
/// 3. 保证资源文件不会被重复下载
|
||||
/// </summary>
|
||||
internal class DownloadManager
|
||||
{
|
||||
private readonly Dictionary<string, DownloaderBase> _downloaders = new Dictionary<string, DownloaderBase>(1000);
|
||||
private readonly List<string> _removeList = new List<string>(1000);
|
||||
|
||||
private uint _breakpointResumeFileSize;
|
||||
|
||||
/// <summary>
|
||||
/// 所属包裹
|
||||
/// </summary>
|
||||
public readonly string PackageName;
|
||||
|
||||
|
||||
public DownloadManager(string packageName)
|
||||
{
|
||||
PackageName = packageName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化
|
||||
/// </summary>
|
||||
public void Initialize(uint breakpointResumeFileSize)
|
||||
{
|
||||
_breakpointResumeFileSize = breakpointResumeFileSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新下载器
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
// 更新下载器
|
||||
_removeList.Clear();
|
||||
foreach (var valuePair in _downloaders)
|
||||
{
|
||||
var downloader = valuePair.Value;
|
||||
downloader.Update();
|
||||
if (downloader.IsDone())
|
||||
{
|
||||
_removeList.Add(valuePair.Key);
|
||||
}
|
||||
}
|
||||
|
||||
// 移除下载器
|
||||
foreach (var key in _removeList)
|
||||
{
|
||||
_downloaders.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁所有下载器
|
||||
/// </summary>
|
||||
public void DestroyAll()
|
||||
{
|
||||
foreach (var valuePair in _downloaders)
|
||||
{
|
||||
var downloader = valuePair.Value;
|
||||
downloader.Abort();
|
||||
}
|
||||
|
||||
_downloaders.Clear();
|
||||
_removeList.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建下载器
|
||||
/// 注意:只有第一次请求的参数才有效
|
||||
/// </summary>
|
||||
public DownloaderBase CreateDownload(BundleInfo bundleInfo, int failedTryAgain, int timeout = 60)
|
||||
{
|
||||
// 查询存在的下载器
|
||||
if (_downloaders.TryGetValue(bundleInfo.CachedDataFilePath, out var downloader))
|
||||
{
|
||||
downloader.Reference();
|
||||
return downloader;
|
||||
}
|
||||
|
||||
// 如果资源已经缓存
|
||||
if (bundleInfo.IsCached())
|
||||
{
|
||||
var completedDownloader = new CompletedDownloader(bundleInfo);
|
||||
return completedDownloader;
|
||||
}
|
||||
|
||||
// 创建新的下载器
|
||||
DownloaderBase newDownloader = null;
|
||||
YooLogger.Log($"Beginning to download bundle : {bundleInfo.Bundle.BundleName} URL : {bundleInfo.RemoteMainURL}");
|
||||
#if UNITY_WEBGL
|
||||
if (bundleInfo.Bundle.Buildpipeline == EDefaultBuildPipeline.RawFileBuildPipeline.ToString())
|
||||
{
|
||||
FileUtility.CreateFileDirectory(bundleInfo.CachedDataFilePath);
|
||||
System.Type requesterType = typeof(FileGeneralRequest);
|
||||
newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Type requesterType = typeof(AssetBundleWebRequest);
|
||||
newDownloader = new WebDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
|
||||
}
|
||||
#else
|
||||
FileUtility.CreateFileDirectory(bundleInfo.CachedDataFilePath);
|
||||
bool resumeDownload = bundleInfo.Bundle.FileSize >= _breakpointResumeFileSize;
|
||||
if (resumeDownload)
|
||||
{
|
||||
System.Type requesterType = typeof(FileResumeRequest);
|
||||
newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Type requesterType = typeof(FileGeneralRequest);
|
||||
newDownloader = new FileDownloader(bundleInfo, requesterType, failedTryAgain, timeout);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 返回新创建的下载器
|
||||
_downloaders.Add(bundleInfo.CachedDataFilePath, newDownloader);
|
||||
newDownloader.Reference();
|
||||
return newDownloader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止不再使用的下载器
|
||||
/// </summary>
|
||||
public void AbortUnusedDownloader()
|
||||
{
|
||||
foreach (var valuePair in _downloaders)
|
||||
{
|
||||
var downloader = valuePair.Value;
|
||||
if (downloader.RefCount <= 0)
|
||||
{
|
||||
downloader.Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fbbbfe01e018b241bf33469f870a4b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,30 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DownloadParam
|
||||
{
|
||||
public readonly int FailedTryAgain;
|
||||
public readonly int Timeout;
|
||||
|
||||
/// <summary>
|
||||
/// 导入的本地文件路径
|
||||
/// </summary>
|
||||
public string ImportFilePath { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 主资源地址
|
||||
/// </summary>
|
||||
public string MainURL { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 备用资源地址
|
||||
/// </summary>
|
||||
public string FallbackURL { set; get; }
|
||||
|
||||
public DownloadParam(int failedTryAgain, int timeout)
|
||||
{
|
||||
FailedTryAgain = failedTryAgain;
|
||||
Timeout = timeout;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56ea224b45d314e4a86b558404e9b6c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,83 @@
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 自定义下载器的请求委托
|
||||
/// </summary>
|
||||
public delegate UnityWebRequest UnityWebRequestDelegate(string url);
|
||||
|
||||
internal class DownloadSystemHelper
|
||||
{
|
||||
public static UnityWebRequestDelegate UnityWebRequestCreater = null;
|
||||
public static UnityWebRequest NewUnityWebRequestGet(string requestURL)
|
||||
{
|
||||
UnityWebRequest webRequest;
|
||||
if (UnityWebRequestCreater != null)
|
||||
webRequest = UnityWebRequestCreater.Invoke(requestURL);
|
||||
else
|
||||
webRequest = new UnityWebRequest(requestURL, UnityWebRequest.kHttpVerbGET);
|
||||
return webRequest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取WWW加载本地资源的路径
|
||||
/// </summary>
|
||||
public static string ConvertToWWWPath(string path)
|
||||
{
|
||||
string url;
|
||||
|
||||
// 获取对应平台的URL地址
|
||||
#if UNITY_EDITOR
|
||||
url = StringUtility.Format("file:///{0}", path);
|
||||
#elif UNITY_WEBGL
|
||||
url = path;
|
||||
#elif UNITY_IPHONE
|
||||
url = StringUtility.Format("file://{0}", path);
|
||||
#elif UNITY_ANDROID
|
||||
if (path.StartsWith("jar:file://"))
|
||||
url = path;
|
||||
else
|
||||
url = StringUtility.Format("jar:file://{0}", path);
|
||||
#elif UNITY_OPENHARMONY
|
||||
if (UnityEngine.Application.streamingAssetsPath.StartsWith("jar:file://"))
|
||||
{
|
||||
if (path.StartsWith("jar:file://"))
|
||||
url = path;
|
||||
else
|
||||
url = StringUtility.Format("jar:file://{0}", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path.StartsWith("file://"))
|
||||
url = path;
|
||||
else
|
||||
url = StringUtility.Format("file://{0}", path);
|
||||
}
|
||||
#elif UNITY_STANDALONE_OSX
|
||||
url = new System.Uri(path).ToString();
|
||||
#elif UNITY_STANDALONE
|
||||
url = StringUtility.Format("file:///{0}", path);
|
||||
#else
|
||||
throw new System.NotImplementedException();
|
||||
#endif
|
||||
|
||||
// For some special cases when users have special characters in their devices, url paths can not be identified correctly.
|
||||
return url.Replace("+", "%2B").Replace("#", "%23").Replace("?", "%3F");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否请求的本地文件
|
||||
/// </summary>
|
||||
public static bool IsRequestLocalFile(string url)
|
||||
{
|
||||
//TODO UNITY_STANDALONE_OSX平台目前无法确定
|
||||
if (url.StartsWith("file:"))
|
||||
return true;
|
||||
if (url.StartsWith("jar:file:"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bacfa8c42e283a45a2d21cbb93d6e5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,28 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class CompletedDownloader : DownloaderBase
|
||||
{
|
||||
public CompletedDownloader(BundleInfo bundleInfo) : base(bundleInfo, null, 0, 0)
|
||||
{
|
||||
DownloadProgress = 1f;
|
||||
DownloadedBytes = (ulong)bundleInfo.Bundle.FileSize;
|
||||
_status = EStatus.Succeed;
|
||||
}
|
||||
|
||||
public override void SendRequest(params object[] param)
|
||||
{
|
||||
}
|
||||
public override void Update()
|
||||
{
|
||||
}
|
||||
public override void Abort()
|
||||
{
|
||||
}
|
||||
public override AssetBundle GetAssetBundle()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c7907ead85e2f94786308b28c37a8aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,182 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class DownloaderBase
|
||||
{
|
||||
public enum EStatus
|
||||
{
|
||||
None = 0,
|
||||
Succeed,
|
||||
Failed
|
||||
}
|
||||
|
||||
protected readonly BundleInfo _bundleInfo;
|
||||
protected readonly System.Type _requesterType;
|
||||
protected readonly int _timeout;
|
||||
protected int _failedTryAgain;
|
||||
|
||||
protected IWebRequester _requester;
|
||||
protected EStatus _status = EStatus.None;
|
||||
protected string _lastestNetError = string.Empty;
|
||||
protected long _lastestHttpCode = 0;
|
||||
|
||||
// 请求次数
|
||||
protected int _requestCount = 0;
|
||||
protected string _requestURL;
|
||||
|
||||
// 超时相关
|
||||
protected bool _isAbort = false;
|
||||
protected ulong _latestDownloadBytes;
|
||||
protected float _latestDownloadRealtime;
|
||||
protected float _tryAgainTimer;
|
||||
|
||||
/// <summary>
|
||||
/// 是否等待异步结束
|
||||
/// 警告:只能用于解压APP内部资源
|
||||
/// </summary>
|
||||
public bool WaitForAsyncComplete = false;
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度(0f~1f)
|
||||
/// </summary>
|
||||
public float DownloadProgress { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 已经下载的总字节数
|
||||
/// </summary>
|
||||
public ulong DownloadedBytes { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 引用计数
|
||||
/// </summary>
|
||||
public int RefCount { private set; get; }
|
||||
|
||||
|
||||
public DownloaderBase(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout)
|
||||
{
|
||||
_bundleInfo = bundleInfo;
|
||||
_requesterType = requesterType;
|
||||
_failedTryAgain = failedTryAgain;
|
||||
_timeout = timeout;
|
||||
}
|
||||
public abstract void SendRequest(params object[] args);
|
||||
public abstract void Update();
|
||||
public abstract void Abort();
|
||||
public abstract AssetBundle GetAssetBundle();
|
||||
|
||||
/// <summary>
|
||||
/// 引用(引用计数递加)
|
||||
/// </summary>
|
||||
public void Reference()
|
||||
{
|
||||
RefCount++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放(引用计数递减)
|
||||
/// </summary>
|
||||
public void Release()
|
||||
{
|
||||
RefCount--;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测下载器是否已经完成(无论成功或失败)
|
||||
/// </summary>
|
||||
public bool IsDone()
|
||||
{
|
||||
return _status == EStatus.Succeed || _status == EStatus.Failed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载过程是否发生错误
|
||||
/// </summary>
|
||||
public bool HasError()
|
||||
{
|
||||
return _status == EStatus.Failed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按照错误级别打印错误
|
||||
/// </summary>
|
||||
public void ReportError()
|
||||
{
|
||||
YooLogger.Error(GetLastError());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按照警告级别打印错误
|
||||
/// </summary>
|
||||
public void ReportWarning()
|
||||
{
|
||||
YooLogger.Warning(GetLastError());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近发生的错误信息
|
||||
/// </summary>
|
||||
public string GetLastError()
|
||||
{
|
||||
return $"Failed to download : {_requestURL} Error : {_lastestNetError} Code : {_lastestHttpCode}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下载文件的大小
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public long GetDownloadFileSize()
|
||||
{
|
||||
return _bundleInfo.Bundle.FileSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下载的资源包名称
|
||||
/// </summary>
|
||||
public string GetDownloadBundleName()
|
||||
{
|
||||
return _bundleInfo.Bundle.BundleName;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络请求地址
|
||||
/// </summary>
|
||||
protected string GetRequestURL()
|
||||
{
|
||||
// 轮流返回请求地址
|
||||
_requestCount++;
|
||||
if (_requestCount % 2 == 0)
|
||||
return _bundleInfo.RemoteFallbackURL;
|
||||
else
|
||||
return _bundleInfo.RemoteMainURL;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 超时判定方法
|
||||
/// </summary>
|
||||
protected void CheckTimeout()
|
||||
{
|
||||
// 注意:在连续时间段内无新增下载数据及判定为超时
|
||||
if (_isAbort == false)
|
||||
{
|
||||
if (_latestDownloadBytes != DownloadedBytes)
|
||||
{
|
||||
_latestDownloadBytes = DownloadedBytes;
|
||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||
}
|
||||
|
||||
float offset = Time.realtimeSinceStartup - _latestDownloadRealtime;
|
||||
if (offset > _timeout)
|
||||
{
|
||||
YooLogger.Warning($"Web file request timeout : {_requestURL}");
|
||||
if (_requester != null)
|
||||
_requester.Abort();
|
||||
_isAbort = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dda4d1eafa2c9f34fade509f8dae9c04
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,216 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件下载器
|
||||
/// </summary>
|
||||
internal sealed class FileDownloader : DownloaderBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
PrepareDownload,
|
||||
CreateDownloader,
|
||||
CheckDownload,
|
||||
VerifyTempFile,
|
||||
WaitingVerifyTempFile,
|
||||
CachingFile,
|
||||
TryAgain,
|
||||
Done,
|
||||
}
|
||||
|
||||
private VerifyTempFileOperation _verifyFileOp = null;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
public FileDownloader(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout) : base(bundleInfo, requesterType, failedTryAgain, timeout)
|
||||
{
|
||||
}
|
||||
public override void SendRequest(params object[] args)
|
||||
{
|
||||
if (_steps == ESteps.None)
|
||||
{
|
||||
_steps = ESteps.PrepareDownload;
|
||||
}
|
||||
}
|
||||
public override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None)
|
||||
return;
|
||||
if (IsDone())
|
||||
return;
|
||||
|
||||
// 准备下载
|
||||
if (_steps == ESteps.PrepareDownload)
|
||||
{
|
||||
// 获取请求地址
|
||||
_requestURL = GetRequestURL();
|
||||
|
||||
// 重置变量
|
||||
DownloadProgress = 0f;
|
||||
DownloadedBytes = 0;
|
||||
|
||||
// 重置变量
|
||||
_isAbort = false;
|
||||
_latestDownloadBytes = 0;
|
||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||
|
||||
// 重置计时器
|
||||
if (_tryAgainTimer > 0f)
|
||||
YooLogger.Warning($"Try again download : {_requestURL}");
|
||||
_tryAgainTimer = 0f;
|
||||
|
||||
_steps = ESteps.CreateDownloader;
|
||||
}
|
||||
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.CreateDownloader)
|
||||
{
|
||||
_requester = (IWebRequester)Activator.CreateInstance(_requesterType);
|
||||
_requester.Create(_requestURL, _bundleInfo);
|
||||
_steps = ESteps.CheckDownload;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckDownload)
|
||||
{
|
||||
_requester.Update();
|
||||
DownloadedBytes = _requester.DownloadedBytes;
|
||||
DownloadProgress = _requester.DownloadProgress;
|
||||
if (_requester.IsDone() == false)
|
||||
{
|
||||
CheckTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
_lastestNetError = _requester.RequestNetError;
|
||||
_lastestHttpCode = _requester.RequestHttpCode;
|
||||
if (_requester.Status != ERequestStatus.Success)
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.VerifyTempFile;
|
||||
}
|
||||
}
|
||||
|
||||
// 验证下载文件
|
||||
if (_steps == ESteps.VerifyTempFile)
|
||||
{
|
||||
VerifyTempFileElement element = new VerifyTempFileElement(_bundleInfo.TempDataFilePath, _bundleInfo.Bundle.FileCRC, _bundleInfo.Bundle.FileSize);
|
||||
_verifyFileOp = VerifyTempFileOperation.CreateOperation(element);
|
||||
OperationSystem.StartOperation(_bundleInfo.Bundle.PackageName, _verifyFileOp);
|
||||
_steps = ESteps.WaitingVerifyTempFile;
|
||||
}
|
||||
|
||||
// 等待验证完成
|
||||
if (_steps == ESteps.WaitingVerifyTempFile)
|
||||
{
|
||||
if (WaitForAsyncComplete)
|
||||
_verifyFileOp.InternalOnUpdate();
|
||||
|
||||
if (_verifyFileOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_verifyFileOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.CachingFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
string tempFilePath = _bundleInfo.TempDataFilePath;
|
||||
if (File.Exists(tempFilePath))
|
||||
File.Delete(tempFilePath);
|
||||
|
||||
_lastestNetError = _verifyFileOp.Error;
|
||||
_steps = ESteps.TryAgain;
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存下载文件
|
||||
if (_steps == ESteps.CachingFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
CachingFile();
|
||||
_status = EStatus.Succeed;
|
||||
_steps = ESteps.Done;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_lastestNetError = e.Message;
|
||||
_steps = ESteps.TryAgain;
|
||||
}
|
||||
}
|
||||
|
||||
// 重新尝试下载
|
||||
if (_steps == ESteps.TryAgain)
|
||||
{
|
||||
if (_failedTryAgain <= 0)
|
||||
{
|
||||
ReportError();
|
||||
_status = EStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
return;
|
||||
}
|
||||
|
||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
||||
if (_tryAgainTimer > 1f)
|
||||
{
|
||||
_failedTryAgain--;
|
||||
_steps = ESteps.PrepareDownload;
|
||||
ReportWarning();
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Abort()
|
||||
{
|
||||
if (_requester != null)
|
||||
_requester.Abort();
|
||||
|
||||
if (IsDone() == false)
|
||||
{
|
||||
_status = EStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
_lastestNetError = "user abort";
|
||||
_lastestHttpCode = 0;
|
||||
}
|
||||
}
|
||||
public override AssetBundle GetAssetBundle()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存下载文件
|
||||
/// </summary>
|
||||
private void CachingFile()
|
||||
{
|
||||
string tempFilePath = _bundleInfo.TempDataFilePath;
|
||||
string infoFilePath = _bundleInfo.CachedInfoFilePath;
|
||||
string dataFilePath = _bundleInfo.CachedDataFilePath;
|
||||
string dataFileCRC = _bundleInfo.Bundle.FileCRC;
|
||||
long dataFileSize = _bundleInfo.Bundle.FileSize;
|
||||
|
||||
if (File.Exists(infoFilePath))
|
||||
File.Delete(infoFilePath);
|
||||
if (File.Exists(dataFilePath))
|
||||
File.Delete(dataFilePath);
|
||||
|
||||
// 移动临时文件路径
|
||||
FileInfo fileInfo = new FileInfo(tempFilePath);
|
||||
fileInfo.MoveTo(dataFilePath);
|
||||
|
||||
// 写入信息文件记录验证数据
|
||||
CacheHelper.WriteInfoToFile(infoFilePath, dataFileCRC, dataFileSize);
|
||||
|
||||
// 记录缓存文件
|
||||
_bundleInfo.CacheRecord();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c6e1a8bc8d5e664395395daa772ddd7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,140 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class WebDownloader : DownloaderBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
PrepareDownload,
|
||||
CreateDownloader,
|
||||
CheckDownload,
|
||||
TryAgain,
|
||||
Done,
|
||||
}
|
||||
|
||||
private ESteps _steps = ESteps.None;
|
||||
private bool _getAssetBundle = false;
|
||||
|
||||
public WebDownloader(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout) : base(bundleInfo, requesterType, failedTryAgain, timeout)
|
||||
{
|
||||
}
|
||||
public override void SendRequest(params object[] args)
|
||||
{
|
||||
if (_steps == ESteps.None)
|
||||
{
|
||||
if (args.Length > 0)
|
||||
{
|
||||
_getAssetBundle = (bool)args[0];
|
||||
}
|
||||
_steps = ESteps.PrepareDownload;
|
||||
}
|
||||
}
|
||||
public override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None)
|
||||
return;
|
||||
if (IsDone())
|
||||
return;
|
||||
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.PrepareDownload)
|
||||
{
|
||||
// 获取请求地址
|
||||
_requestURL = GetRequestURL();
|
||||
|
||||
// 重置变量
|
||||
DownloadProgress = 0f;
|
||||
DownloadedBytes = 0;
|
||||
|
||||
// 重置变量
|
||||
_isAbort = false;
|
||||
_latestDownloadBytes = 0;
|
||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||
|
||||
// 重置计时器
|
||||
if (_tryAgainTimer > 0f)
|
||||
YooLogger.Warning($"Try again download : {_requestURL}");
|
||||
_tryAgainTimer = 0f;
|
||||
|
||||
_steps = ESteps.CreateDownloader;
|
||||
}
|
||||
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.CreateDownloader)
|
||||
{
|
||||
_requester = (IWebRequester)Activator.CreateInstance(_requesterType);
|
||||
_requester.Create(_requestURL, _bundleInfo, _getAssetBundle);
|
||||
_steps = ESteps.CheckDownload;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckDownload)
|
||||
{
|
||||
_requester.Update();
|
||||
DownloadedBytes = _requester.DownloadedBytes;
|
||||
DownloadProgress = _requester.DownloadProgress;
|
||||
if (_requester.IsDone() == false)
|
||||
{
|
||||
CheckTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
_lastestNetError = _requester.RequestNetError;
|
||||
_lastestHttpCode = _requester.RequestHttpCode;
|
||||
if (_requester.Status != ERequestStatus.Success)
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
}
|
||||
else
|
||||
{
|
||||
_status = EStatus.Succeed;
|
||||
_steps = ESteps.Done;
|
||||
}
|
||||
}
|
||||
|
||||
// 重新尝试下载
|
||||
if (_steps == ESteps.TryAgain)
|
||||
{
|
||||
if (_failedTryAgain <= 0)
|
||||
{
|
||||
ReportError();
|
||||
_status = EStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
return;
|
||||
}
|
||||
|
||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
||||
if (_tryAgainTimer > 1f)
|
||||
{
|
||||
_failedTryAgain--;
|
||||
_steps = ESteps.PrepareDownload;
|
||||
ReportWarning();
|
||||
YooLogger.Warning($"Try again download : {_requestURL}");
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Abort()
|
||||
{
|
||||
if (_requester != null)
|
||||
_requester.Abort();
|
||||
|
||||
if (IsDone() == false)
|
||||
{
|
||||
_status = EStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
_lastestNetError = "user abort";
|
||||
_lastestHttpCode = 0;
|
||||
}
|
||||
}
|
||||
public override AssetBundle GetAssetBundle()
|
||||
{
|
||||
return (AssetBundle)_requester.GetRequestObject();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41bc4bc56f59ddb4b8925f9536bbbfbc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d29a9623b2b346e439b7a7e37fafa781
|
||||
guid: a8f060786f8775b4a82cc3f55d9135e2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a93a516506b2b5c4492fdefe26eb1175
|
||||
guid: 4630dac2050606043bb146325fdce6ad
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
@@ -0,0 +1,77 @@
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityWebDataRequestOperation : UnityWebRequestOperation
|
||||
{
|
||||
private UnityWebRequestAsyncOperation _requestOperation;
|
||||
|
||||
/// <summary>
|
||||
/// 请求结果
|
||||
/// </summary>
|
||||
public byte[] Result { private set; get; }
|
||||
|
||||
|
||||
internal UnityWebDataRequestOperation(string url, int timeout = 60) : base(url, timeout)
|
||||
{
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
_latestDownloadBytes = 0;
|
||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
Progress = _requestOperation.progress;
|
||||
if (_requestOperation.isDone == false)
|
||||
{
|
||||
CheckRequestTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = _webRequest.downloadHandler.data;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeRequest();
|
||||
}
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
DisposeRequest();
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_requestOperation = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityWebFileRequestOperation : UnityWebRequestOperation
|
||||
{
|
||||
private UnityWebRequestAsyncOperation _requestOperation;
|
||||
private readonly string _fileSavePath;
|
||||
|
||||
internal UnityWebFileRequestOperation(string url, string fileSavePath, int timeout = 60) : base(url, timeout)
|
||||
{
|
||||
_fileSavePath = fileSavePath;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
_latestDownloadBytes = 0;
|
||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
Progress = _requestOperation.progress;
|
||||
if (_requestOperation.isDone == false)
|
||||
{
|
||||
CheckRequestTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeRequest();
|
||||
}
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
DisposeRequest();
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
DownloadHandlerFile handler = new DownloadHandlerFile(_fileSavePath);
|
||||
handler.removeFileOnAbort = true;
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_requestOperation = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,99 +6,58 @@ using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class UnityWebRequesterBase
|
||||
internal abstract class UnityWebRequestOperation : AsyncOperationBase
|
||||
{
|
||||
protected enum ESteps
|
||||
{
|
||||
None,
|
||||
CreateRequest,
|
||||
Download,
|
||||
Done,
|
||||
}
|
||||
|
||||
protected UnityWebRequest _webRequest;
|
||||
protected UnityWebRequestAsyncOperation _operationHandle;
|
||||
protected readonly string _requestURL;
|
||||
protected ESteps _steps = ESteps.None;
|
||||
|
||||
// 超时相关
|
||||
private float _timeout;
|
||||
protected readonly float _timeout;
|
||||
protected ulong _latestDownloadBytes;
|
||||
protected float _latestDownloadRealtime;
|
||||
private bool _isAbort = false;
|
||||
private ulong _latestDownloadBytes;
|
||||
private float _latestDownloadRealtime;
|
||||
|
||||
/// <summary>
|
||||
/// 请求URL地址
|
||||
/// </summary>
|
||||
public string URL { protected set; get; }
|
||||
|
||||
|
||||
protected void ResetTimeout(float timeout)
|
||||
public string URL
|
||||
{
|
||||
get { return _requestURL; }
|
||||
}
|
||||
|
||||
internal UnityWebRequestOperation(string url, int timeout)
|
||||
{
|
||||
_requestURL = url;
|
||||
_timeout = timeout;
|
||||
_latestDownloadBytes = 0;
|
||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放下载器
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
protected void DisposeRequest()
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
_operationHandle = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否完毕(无论成功失败)
|
||||
/// </summary>
|
||||
public bool IsDone()
|
||||
{
|
||||
if (_operationHandle == null)
|
||||
return false;
|
||||
return _operationHandle.isDone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度
|
||||
/// </summary>
|
||||
public float Progress()
|
||||
{
|
||||
if (_operationHandle == null)
|
||||
return 0;
|
||||
return _operationHandle.progress;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载是否发生错误
|
||||
/// </summary>
|
||||
public bool HasError()
|
||||
{
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
return _webRequest.result != UnityWebRequest.Result.Success;
|
||||
#else
|
||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取错误信息
|
||||
/// </summary>
|
||||
public string GetError()
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
return $"URL : {URL} Error : {_webRequest.error}";
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测超时
|
||||
/// </summary>
|
||||
public void CheckTimeout()
|
||||
protected void CheckRequestTimeout()
|
||||
{
|
||||
// 注意:在连续时间段内无新增下载数据及判定为超时
|
||||
if (_isAbort == false)
|
||||
{
|
||||
if (_latestDownloadBytes != _webRequest.downloadedBytes)
|
||||
if ( _latestDownloadBytes != _webRequest.downloadedBytes)
|
||||
{
|
||||
_latestDownloadBytes = _webRequest.downloadedBytes;
|
||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||
@@ -112,5 +71,33 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测请求结果
|
||||
/// </summary>
|
||||
protected bool CheckRequestResult()
|
||||
{
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
if (_webRequest.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
Error = $"URL : {_requestURL} Error : {_webRequest.error}";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
||||
{
|
||||
Error = $"URL : {_requestURL} Error : {_webRequest.error}";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityWebTextRequestOperation : UnityWebRequestOperation
|
||||
{
|
||||
private UnityWebRequestAsyncOperation _requestOperation;
|
||||
|
||||
/// <summary>
|
||||
/// 请求结果
|
||||
/// </summary>
|
||||
public string Result { private set; get; }
|
||||
|
||||
|
||||
internal UnityWebTextRequestOperation(string url, int timeout = 60) : base(url, timeout)
|
||||
{
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
_latestDownloadBytes = 0;
|
||||
_latestDownloadRealtime = Time.realtimeSinceStartup;
|
||||
|
||||
CreateWebRequest();
|
||||
_steps = ESteps.Download;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
Progress = _requestOperation.progress;
|
||||
if (_requestOperation.isDone == false)
|
||||
{
|
||||
CheckRequestTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = _webRequest.downloadHandler.text;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeRequest();
|
||||
}
|
||||
}
|
||||
internal override void InternalAbort()
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
DisposeRequest();
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
|
||||
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_requestOperation = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a488de5dcd6f4c448a47c4b574d5c9bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a97534752300584a9b8c60c04c6a6a8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,145 +0,0 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class AssetBundleWebRequest : IWebRequester
|
||||
{
|
||||
private UnityWebRequest _webRequest;
|
||||
private DownloadHandlerAssetBundle _downloadhandler;
|
||||
private AssetBundle _cacheAssetBundle;
|
||||
private bool _getAssetBundle = false;
|
||||
|
||||
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
|
||||
public float DownloadProgress { private set; get; }
|
||||
public ulong DownloadedBytes { private set; get; }
|
||||
public string RequestNetError { private set; get; }
|
||||
public long RequestHttpCode { private set; get; }
|
||||
|
||||
public AssetBundleWebRequest() { }
|
||||
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
|
||||
{
|
||||
if (Status != ERequestStatus.None)
|
||||
throw new System.Exception("Should never get here !");
|
||||
|
||||
if (args.Length == 0)
|
||||
throw new System.Exception("Not found param value");
|
||||
|
||||
// 解析附加参数
|
||||
_getAssetBundle = (bool)args[0];
|
||||
|
||||
// 创建下载器
|
||||
_webRequest = DownloadHelper.NewRequest(requestURL);
|
||||
if (CacheHelper.DisableUnityCacheOnWebGL)
|
||||
{
|
||||
uint crc = bundleInfo.Bundle.UnityCRC;
|
||||
_downloadhandler = new DownloadHandlerAssetBundle(requestURL, crc);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint crc = bundleInfo.Bundle.UnityCRC;
|
||||
var hash = Hash128.Parse(bundleInfo.Bundle.FileHash);
|
||||
_downloadhandler = new DownloadHandlerAssetBundle(requestURL, hash, crc);
|
||||
}
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
_downloadhandler.autoLoadAssetBundle = false;
|
||||
#endif
|
||||
_webRequest.downloadHandler = _downloadhandler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_webRequest.SendWebRequest();
|
||||
Status = ERequestStatus.InProgress;
|
||||
}
|
||||
public void Update()
|
||||
{
|
||||
if (Status == ERequestStatus.None)
|
||||
return;
|
||||
if (IsDone())
|
||||
return;
|
||||
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = _webRequest.downloadedBytes;
|
||||
if (_webRequest.isDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
RequestHttpCode = _webRequest.responseCode;
|
||||
if (_webRequest.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
RequestNetError = _webRequest.error;
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ERequestStatus.Success;
|
||||
}
|
||||
#else
|
||||
RequestHttpCode = _webRequest.responseCode;
|
||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
||||
{
|
||||
RequestNetError = _webRequest.error;
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ERequestStatus.Success;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 缓存加载的AssetBundle对象
|
||||
if (Status == ERequestStatus.Success)
|
||||
{
|
||||
if (_getAssetBundle)
|
||||
{
|
||||
_cacheAssetBundle = _downloadhandler.assetBundle;
|
||||
if (_cacheAssetBundle == null)
|
||||
{
|
||||
RequestNetError = "assetBundle is null";
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 最终释放下载器
|
||||
DisposeWebRequest();
|
||||
}
|
||||
public void Abort()
|
||||
{
|
||||
// 如果下载任务还未开始
|
||||
if (Status == ERequestStatus.None)
|
||||
{
|
||||
RequestNetError = "user cancel";
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 注意:为了防止同一个文件强制停止之后立马创建新的请求,应该让进行中的请求自然终止。
|
||||
if (_webRequest != null)
|
||||
{
|
||||
if (_webRequest.isDone == false)
|
||||
_webRequest.Abort(); // If in progress, halts the UnityWebRequest as soon as possible.
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool IsDone()
|
||||
{
|
||||
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public object GetRequestObject()
|
||||
{
|
||||
return _cacheAssetBundle;
|
||||
}
|
||||
private void DisposeWebRequest()
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34efa85440da15247b570a98b0971282
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,107 +0,0 @@
|
||||
using System.IO;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class FileGeneralRequest : IWebRequester
|
||||
{
|
||||
private UnityWebRequest _webRequest;
|
||||
|
||||
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
|
||||
public float DownloadProgress { private set; get; }
|
||||
public ulong DownloadedBytes { private set; get; }
|
||||
public string RequestNetError { private set; get; }
|
||||
public long RequestHttpCode { private set; get; }
|
||||
|
||||
public FileGeneralRequest() { }
|
||||
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
|
||||
{
|
||||
if (Status != ERequestStatus.None)
|
||||
throw new System.Exception("Should never get here !");
|
||||
|
||||
string tempFilePath = bundleInfo.TempDataFilePath;
|
||||
|
||||
// 删除临时文件
|
||||
if (File.Exists(tempFilePath))
|
||||
File.Delete(tempFilePath);
|
||||
|
||||
// 创建下载器
|
||||
_webRequest = DownloadHelper.NewRequest(requestURL);
|
||||
DownloadHandlerFile handler = new DownloadHandlerFile(tempFilePath);
|
||||
handler.removeFileOnAbort = true;
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_webRequest.SendWebRequest();
|
||||
Status = ERequestStatus.InProgress;
|
||||
}
|
||||
public void Update()
|
||||
{
|
||||
if (Status == ERequestStatus.None)
|
||||
return;
|
||||
if (IsDone())
|
||||
return;
|
||||
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = _webRequest.downloadedBytes;
|
||||
if (_webRequest.isDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
RequestHttpCode = _webRequest.responseCode;
|
||||
if (_webRequest.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
RequestNetError = _webRequest.error;
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ERequestStatus.Success;
|
||||
}
|
||||
#else
|
||||
RequestHttpCode = _webRequest.responseCode;
|
||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
||||
{
|
||||
RequestNetError = _webRequest.error;
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ERequestStatus.Success;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 最终释放下载器
|
||||
DisposeWebRequest();
|
||||
}
|
||||
public void Abort()
|
||||
{
|
||||
DisposeWebRequest();
|
||||
if (IsDone() == false)
|
||||
{
|
||||
RequestNetError = "user abort";
|
||||
RequestHttpCode = 0;
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
}
|
||||
public bool IsDone()
|
||||
{
|
||||
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public object GetRequestObject()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
private void DisposeWebRequest()
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
_webRequest.Dispose(); //注意:引擎底层会自动调用Abort方法
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2f339136a4269343a3b5ab80450b889
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,150 +0,0 @@
|
||||
using System.IO;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class FileResumeRequest : IWebRequester
|
||||
{
|
||||
private string _tempFilePath;
|
||||
private UnityWebRequest _webRequest;
|
||||
private DownloadHandlerFileRange _downloadHandle;
|
||||
private ulong _fileOriginLength = 0;
|
||||
|
||||
public ERequestStatus Status { private set; get; } = ERequestStatus.None;
|
||||
public float DownloadProgress { private set; get; }
|
||||
public ulong DownloadedBytes { private set; get; }
|
||||
public string RequestNetError { private set; get; }
|
||||
public long RequestHttpCode { private set; get; }
|
||||
|
||||
public FileResumeRequest() { }
|
||||
public void Create(string requestURL, BundleInfo bundleInfo, params object[] args)
|
||||
{
|
||||
if (Status != ERequestStatus.None)
|
||||
throw new System.Exception("Should never get here !");
|
||||
|
||||
_tempFilePath = bundleInfo.TempDataFilePath;
|
||||
long fileBytes = bundleInfo.Bundle.FileSize;
|
||||
|
||||
// 获取下载的起始位置
|
||||
long fileLength = -1;
|
||||
if (File.Exists(_tempFilePath))
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(_tempFilePath);
|
||||
fileLength = fileInfo.Length;
|
||||
_fileOriginLength = (ulong)fileLength;
|
||||
DownloadedBytes = _fileOriginLength;
|
||||
}
|
||||
|
||||
// 检测下载起始位置是否有效
|
||||
if (fileLength >= fileBytes)
|
||||
{
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
|
||||
// 创建下载器
|
||||
_webRequest = DownloadHelper.NewRequest(requestURL);
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
var handler = new DownloadHandlerFile(_tempFilePath, true);
|
||||
handler.removeFileOnAbort = false;
|
||||
#else
|
||||
var handler = new DownloadHandlerFileRange(tempFilePath, _bundleInfo.Bundle.FileSize, _webRequest);
|
||||
_downloadHandle = handler;
|
||||
#endif
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
if (fileLength > 0)
|
||||
_webRequest.SetRequestHeader("Range", $"bytes={fileLength}-");
|
||||
_webRequest.SendWebRequest();
|
||||
Status = ERequestStatus.InProgress;
|
||||
}
|
||||
public void Update()
|
||||
{
|
||||
if (Status == ERequestStatus.None)
|
||||
return;
|
||||
if (IsDone())
|
||||
return;
|
||||
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = _fileOriginLength + _webRequest.downloadedBytes;
|
||||
if (_webRequest.isDone == false)
|
||||
return;
|
||||
|
||||
// 检查网络错误
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
RequestHttpCode = _webRequest.responseCode;
|
||||
if (_webRequest.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
RequestNetError = _webRequest.error;
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ERequestStatus.Success;
|
||||
}
|
||||
#else
|
||||
RequestHttpCode = _webRequest.responseCode;
|
||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
||||
{
|
||||
RequestNetError = _webRequest.error;
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ERequestStatus.Success;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 注意:下载断点续传文件发生特殊错误码之后删除文件
|
||||
if (Status == ERequestStatus.Error)
|
||||
{
|
||||
if (DownloadHelper.ClearFileResponseCodes != null)
|
||||
{
|
||||
if (DownloadHelper.ClearFileResponseCodes.Contains(RequestHttpCode))
|
||||
{
|
||||
if (File.Exists(_tempFilePath))
|
||||
File.Delete(_tempFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 最终释放下载器
|
||||
DisposeWebRequest();
|
||||
}
|
||||
public void Abort()
|
||||
{
|
||||
DisposeWebRequest();
|
||||
if (IsDone() == false)
|
||||
{
|
||||
RequestNetError = "user abort";
|
||||
RequestHttpCode = 0;
|
||||
Status = ERequestStatus.Error;
|
||||
}
|
||||
}
|
||||
public bool IsDone()
|
||||
{
|
||||
if (Status == ERequestStatus.Success || Status == ERequestStatus.Error)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public object GetRequestObject()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
private void DisposeWebRequest()
|
||||
{
|
||||
if (_downloadHandle != null)
|
||||
{
|
||||
_downloadHandle.Cleanup();
|
||||
_downloadHandle = null;
|
||||
}
|
||||
|
||||
if (_webRequest != null)
|
||||
{
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 816bf5396d7570e4ab28f1af407bc10f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,65 +0,0 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal enum ERequestStatus
|
||||
{
|
||||
None,
|
||||
InProgress,
|
||||
Error,
|
||||
Success,
|
||||
}
|
||||
|
||||
internal interface IWebRequester
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务状态
|
||||
/// </summary>
|
||||
public ERequestStatus Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度(0f~1f)
|
||||
/// </summary>
|
||||
public float DownloadProgress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 已经下载的总字节数
|
||||
/// </summary>
|
||||
public ulong DownloadedBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回的网络错误
|
||||
/// </summary>
|
||||
public string RequestNetError { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回的HTTP CODE
|
||||
/// </summary>
|
||||
public long RequestHttpCode { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建任务
|
||||
/// </summary>
|
||||
public void Create(string url, BundleInfo bundleInfo, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// 更新任务
|
||||
/// </summary>
|
||||
public void Update();
|
||||
|
||||
/// <summary>
|
||||
/// 终止任务
|
||||
/// </summary>
|
||||
public void Abort();
|
||||
|
||||
/// <summary>
|
||||
/// 是否已经完成(无论成功或失败)
|
||||
/// </summary>
|
||||
public bool IsDone();
|
||||
|
||||
/// <summary>
|
||||
/// 获取请求的对象
|
||||
/// </summary>
|
||||
public object GetRequestObject();
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d80b965d56870b43af1bf6943015914
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,38 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 同步其它线程里的回调到主线程里
|
||||
/// 注意:Unity3D中需要设置Scripting Runtime Version为.NET4.6
|
||||
/// </summary>
|
||||
internal sealed class ThreadSyncContext : SynchronizationContext
|
||||
{
|
||||
private readonly ConcurrentQueue<Action> _safeQueue = new ConcurrentQueue<Action>();
|
||||
|
||||
/// <summary>
|
||||
/// 更新同步队列
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_safeQueue.TryDequeue(out Action action) == false)
|
||||
return;
|
||||
action.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向同步队列里投递一个回调方法
|
||||
/// </summary>
|
||||
public override void Post(SendOrPostCallback callback, object state)
|
||||
{
|
||||
Action action = new Action(() => { callback(state); });
|
||||
_safeQueue.Enqueue(action);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c8ce2c52a3e9964fa50a9c031e4e593
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityWebDataRequester : UnityWebRequesterBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 发送GET请求
|
||||
/// </summary>
|
||||
public void SendRequest(string url, int timeout = 60)
|
||||
{
|
||||
if (_webRequest == null)
|
||||
{
|
||||
URL = url;
|
||||
ResetTimeout(timeout);
|
||||
|
||||
_webRequest = DownloadHelper.NewRequest(URL);
|
||||
DownloadHandlerBuffer handler = new DownloadHandlerBuffer();
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_operationHandle = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下载的字节数据
|
||||
/// </summary>
|
||||
public byte[] GetData()
|
||||
{
|
||||
if (_webRequest != null && IsDone())
|
||||
return _webRequest.downloadHandler.data;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下载的文本数据
|
||||
/// </summary>
|
||||
public string GetText()
|
||||
{
|
||||
if (_webRequest != null && IsDone())
|
||||
return _webRequest.downloadHandler.text;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class UnityWebFileRequester : UnityWebRequesterBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 发送GET请求
|
||||
/// </summary>
|
||||
public void SendRequest(string url, string fileSavePath, int timeout = 60)
|
||||
{
|
||||
if (_webRequest == null)
|
||||
{
|
||||
URL = url;
|
||||
ResetTimeout(timeout);
|
||||
|
||||
_webRequest = DownloadHelper.NewRequest(URL);
|
||||
DownloadHandlerFile handler = new DownloadHandlerFile(fileSavePath);
|
||||
handler.removeFileOnAbort = true;
|
||||
_webRequest.downloadHandler = handler;
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_operationHandle = _webRequest.SendWebRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public class RequestHelper
|
||||
internal class WebRequestCounter
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录网络请求失败事件的次数
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96a75a20111d6124696665e7aac3564c
|
||||
guid: b826e89349869884994512ad083e53cc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a82eeb6a47cd02c4cb38e851c8ed8784
|
||||
guid: 5d7171aa14ba0e649900533bfeed0edb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
@@ -0,0 +1,16 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
public static class AssetHandleExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 等待异步执行完毕
|
||||
/// </summary>
|
||||
public static AssetHandle WaitForAsyncOperationComplete(this AssetHandle thisHandle)
|
||||
{
|
||||
thisHandle.WaitForAsyncComplete();
|
||||
return thisHandle;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0893ac05d109894e9acb6deeb688ee5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,12 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
public static class HandleBaseExtension
|
||||
{
|
||||
public static bool IsSucceed(this HandleBase thisHandle)
|
||||
{
|
||||
return thisHandle.IsDone && thisHandle.Status == EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03c367406c5062c41ba3290201be20c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5280dfac6a481ee429c769ba5688c9d2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccb22c5c90bfe2f43a0f83f873dd6646
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 879f2b393f883554899ab3345f0dc998
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,64 @@
|
||||
#if UNITY_WEBGL && DOUYINMINIGAME
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using TTSDK;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class TTAssetBundleResult : BundleResult
|
||||
{
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly PackageBundle _packageBundle;
|
||||
private readonly AssetBundle _assetBundle;
|
||||
|
||||
public TTAssetBundleResult(IFileSystem fileSystem, PackageBundle packageBundle, AssetBundle assetBundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageBundle = packageBundle;
|
||||
_assetBundle = assetBundle;
|
||||
}
|
||||
|
||||
public override void UnloadBundleFile()
|
||||
{
|
||||
if (_assetBundle != null)
|
||||
{
|
||||
_assetBundle.TTUnload(true);
|
||||
}
|
||||
}
|
||||
public override string GetBundleFilePath()
|
||||
{
|
||||
return _fileSystem.GetBundleFilePath(_packageBundle);
|
||||
}
|
||||
public override byte[] ReadBundleFileData()
|
||||
{
|
||||
return _fileSystem.ReadBundleFileData(_packageBundle);
|
||||
}
|
||||
public override string ReadBundleFileText()
|
||||
{
|
||||
return _fileSystem.ReadBundleFileText(_packageBundle);
|
||||
}
|
||||
|
||||
public override FSLoadAssetOperation LoadAssetAsync(AssetInfo assetInfo)
|
||||
{
|
||||
var operation = new AssetBundleLoadAssetOperation(_packageBundle, _assetBundle, assetInfo);
|
||||
return operation;
|
||||
}
|
||||
public override FSLoadAllAssetsOperation LoadAllAssetsAsync(AssetInfo assetInfo)
|
||||
{
|
||||
var operation = new AssetBundleLoadAllAssetsOperation(_packageBundle, _assetBundle, assetInfo);
|
||||
return operation;
|
||||
}
|
||||
public override FSLoadSubAssetsOperation LoadSubAssetsAsync(AssetInfo assetInfo)
|
||||
{
|
||||
var operation = new AssetBundleLoadSubAssetsOperation(_packageBundle, _assetBundle, assetInfo);
|
||||
return operation;
|
||||
}
|
||||
public override FSLoadSceneOperation LoadSceneOperation(AssetInfo assetInfo, LoadSceneParameters loadParams, bool suspendLoad)
|
||||
{
|
||||
var operation = new AssetBundleLoadSceneOperation(assetInfo, loadParams, suspendLoad);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80ce0631d38cf74458c902fb325afb81
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8cba5e0b26df8ee40a93d697f889e33d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,101 @@
|
||||
#if UNITY_WEBGL && DOUYINMINIGAME
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using YooAsset;
|
||||
|
||||
internal class TTFSDownloadFileOperation : DefaultDownloadFileOperation
|
||||
{
|
||||
private TiktokFileSystem _fileSystem;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal TTFSDownloadFileOperation(TiktokFileSystem fileSystem, PackageBundle bundle, DownloadParam param) : base(bundle, param)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.CreateRequest;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
// 创建下载器
|
||||
if (_steps == ESteps.CreateRequest)
|
||||
{
|
||||
// 获取请求地址
|
||||
_requestURL = GetRequestURL();
|
||||
|
||||
// 重置变量
|
||||
ResetRequestFiled();
|
||||
|
||||
// 创建下载器
|
||||
CreateWebRequest();
|
||||
|
||||
_steps = ESteps.CheckRequest;
|
||||
}
|
||||
|
||||
// 检测下载结果
|
||||
if (_steps == ESteps.CheckRequest)
|
||||
{
|
||||
DownloadProgress = _webRequest.downloadProgress;
|
||||
DownloadedBytes = (long)_webRequest.downloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
if (_webRequest.isDone == false)
|
||||
{
|
||||
CheckRequestTimeout();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查网络错误
|
||||
if (CheckRequestResult())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.TryAgain;
|
||||
}
|
||||
|
||||
// 注意:最终释放请求器
|
||||
DisposeWebRequest();
|
||||
}
|
||||
|
||||
// 重新尝试下载
|
||||
if (_steps == ESteps.TryAgain)
|
||||
{
|
||||
if (FailedTryAgain <= 0)
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
_steps = ESteps.Done;
|
||||
YooLogger.Error(Error);
|
||||
return;
|
||||
}
|
||||
|
||||
_tryAgainTimer += Time.unscaledDeltaTime;
|
||||
if (_tryAgainTimer > 1f)
|
||||
{
|
||||
FailedTryAgain--;
|
||||
_steps = ESteps.CreateRequest;
|
||||
YooLogger.Warning(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWebRequest()
|
||||
{
|
||||
//TODO : 抖音小游戏没有找到预下载方法
|
||||
_webRequest = UnityWebRequest.Get(_requestURL);
|
||||
_webRequest.disposeDownloadHandlerOnDispose = true;
|
||||
_webRequest.SendWebRequest();
|
||||
}
|
||||
private void DisposeWebRequest()
|
||||
{
|
||||
if (_webRequest != null)
|
||||
{
|
||||
//注意:引擎底层会自动调用Abort方法
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bdf53359f9e17b41b08982a2be2098c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,20 @@
|
||||
#if UNITY_WEBGL && DOUYINMINIGAME
|
||||
using YooAsset;
|
||||
|
||||
internal partial class TTFSInitializeOperation : FSInitializeFileSystemOperation
|
||||
{
|
||||
private readonly TiktokFileSystem _fileSystem;
|
||||
|
||||
public TTFSInitializeOperation(TiktokFileSystem fileSystem)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 614227bf558da7149a7eb6de7dfa1a21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,98 @@
|
||||
#if UNITY_WEBGL && DOUYINMINIGAME
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using YooAsset;
|
||||
|
||||
internal class TTFSLoadBundleOperation : FSLoadBundleOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
DownloadAssetBundle,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly TiktokFileSystem _fileSystem;
|
||||
private readonly PackageBundle _bundle;
|
||||
private DownloadAssetBundleOperation _downloadAssetBundleOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal TTFSLoadBundleOperation(TiktokFileSystem fileSystem, PackageBundle bundle)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_bundle = bundle;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.DownloadAssetBundle;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.DownloadAssetBundle)
|
||||
{
|
||||
if (_downloadAssetBundleOp == null)
|
||||
{
|
||||
DownloadParam downloadParam = new DownloadParam(int.MaxValue, 60);
|
||||
downloadParam.MainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName); ;
|
||||
downloadParam.FallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName);
|
||||
|
||||
if (_bundle.Encrypted)
|
||||
{
|
||||
_downloadAssetBundleOp = new DownloadWebEncryptAssetBundleOperation(false, _fileSystem.DecryptionServices, _bundle, downloadParam);
|
||||
_downloadAssetBundleOp.StartOperation();
|
||||
AddChildOperation(_downloadAssetBundleOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
_downloadAssetBundleOp = new DownloadTiktokAssetBundleOperation(_bundle, downloadParam);
|
||||
_downloadAssetBundleOp.StartOperation();
|
||||
AddChildOperation(_downloadAssetBundleOp);
|
||||
}
|
||||
}
|
||||
|
||||
_downloadAssetBundleOp.UpdateOperation();
|
||||
DownloadProgress = _downloadAssetBundleOp.DownloadProgress;
|
||||
DownloadedBytes = (long)_downloadAssetBundleOp.DownloadedBytes;
|
||||
Progress = DownloadProgress;
|
||||
if (_downloadAssetBundleOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_downloadAssetBundleOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
var assetBundle = _downloadAssetBundleOp.Result;
|
||||
if (assetBundle == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(DownloadAssetBundleOperation)} loaded asset bundle is null !";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Result = new TTAssetBundleResult(_fileSystem, _bundle, assetBundle);
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloadAssetBundleOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal override void InternalWaitForAsyncComplete()
|
||||
{
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "WebGL platform not support sync load method !";
|
||||
UnityEngine.Debug.LogError(Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19997de7b89b54445961e8b973f43ab3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,92 @@
|
||||
#if UNITY_WEBGL && DOUYINMINIGAME
|
||||
using YooAsset;
|
||||
|
||||
internal class TTFSLoadPackageManifestOperation : FSLoadPackageManifestOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
RequestPackageHash,
|
||||
LoadPackageManifest,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly TiktokFileSystem _fileSystem;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private RequestTiktokPackageHashOperation _requestPackageHashOp;
|
||||
private LoadTiktokPackageManifestOperation _loadPackageManifestOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
public TTFSLoadPackageManifestOperation(TiktokFileSystem fileSystem, string packageVersion, int timeout)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_packageVersion = packageVersion;
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.RequestPackageHash;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.RequestPackageHash)
|
||||
{
|
||||
if (_requestPackageHashOp == null)
|
||||
{
|
||||
_requestPackageHashOp = new RequestTiktokPackageHashOperation(_fileSystem, _packageVersion, _timeout);
|
||||
_requestPackageHashOp.StartOperation();
|
||||
AddChildOperation(_requestPackageHashOp);
|
||||
}
|
||||
|
||||
_requestPackageHashOp.UpdateOperation();
|
||||
if (_requestPackageHashOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_requestPackageHashOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.LoadPackageManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _requestPackageHashOp.Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadPackageManifest)
|
||||
{
|
||||
if (_loadPackageManifestOp == null)
|
||||
{
|
||||
string packageHash = _requestPackageHashOp.PackageHash;
|
||||
_loadPackageManifestOp = new LoadTiktokPackageManifestOperation(_fileSystem, _packageVersion, packageHash, _timeout);
|
||||
_loadPackageManifestOp.StartOperation();
|
||||
AddChildOperation(_loadPackageManifestOp);
|
||||
}
|
||||
|
||||
_loadPackageManifestOp.UpdateOperation();
|
||||
Progress = _loadPackageManifestOp.Progress;
|
||||
if (_loadPackageManifestOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_loadPackageManifestOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Manifest = _loadPackageManifestOp.Manifest;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _loadPackageManifestOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2850c0b0e742f824f9d1f12b7d68b806
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,62 @@
|
||||
#if UNITY_WEBGL && DOUYINMINIGAME
|
||||
using YooAsset;
|
||||
|
||||
internal class TTFSRequestPackageVersionOperation : FSRequestPackageVersionOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
RequestPackageVersion,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly TiktokFileSystem _fileSystem;
|
||||
private readonly int _timeout;
|
||||
private RequestTiktokPackageVersionOperation _requestPackageVersionOp;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
|
||||
internal TTFSRequestPackageVersionOperation(TiktokFileSystem fileSystem, int timeout)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_timeout = timeout;
|
||||
}
|
||||
internal override void InternalStart()
|
||||
{
|
||||
_steps = ESteps.RequestPackageVersion;
|
||||
}
|
||||
internal override void InternalUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.RequestPackageVersion)
|
||||
{
|
||||
if (_requestPackageVersionOp == null)
|
||||
{
|
||||
_requestPackageVersionOp = new RequestTiktokPackageVersionOperation(_fileSystem, _timeout);
|
||||
_requestPackageVersionOp.StartOperation();
|
||||
AddChildOperation(_requestPackageVersionOp);
|
||||
}
|
||||
|
||||
_requestPackageVersionOp.UpdateOperation();
|
||||
Progress = _requestPackageVersionOp.Progress;
|
||||
if (_requestPackageVersionOp.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_requestPackageVersionOp.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
PackageVersion = _requestPackageVersionOp.PackageVersion;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _requestPackageVersionOp.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8210185faba92a3479bf6713abab1f19
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 101c97835f86e9147993961f514caf2c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user