Compare commits

..

23 Commits

Author SHA1 Message Date
何冠峰
89e23e0df8 perf : 优化异步操作系统的繁忙检测机制
默认情况下不必检测
2025-08-16 16:53:28 +08:00
何冠峰
e2f582834e fix #611 2025-08-13 10:29:41 +08:00
何冠峰
d2c2844f61 update mini game
移除冗余代码
2025-08-13 10:29:25 +08:00
何冠峰
1de64278ad sample : 新增生成内置清单文件的页面工具 2025-08-04 18:36:43 +08:00
何冠峰
227f2332a9 refactor : 重构内置文件的加载和拷贝逻辑。
优先使用File类拷贝文件
2025-08-04 17:26:57 +08:00
何冠峰
131614687c Update LICENSE 2025-07-30 14:18:26 +08:00
何冠峰
b8ec902f60 perf : IsUnpackBundleFile方法设置为虚方法 2025-07-29 14:34:59 +08:00
何冠峰
eb3e29b6ad style : 修改形参注释 2025-07-29 14:33:54 +08:00
何冠峰
11ed9d391a build : 预留构建Mono脚本资源包方法。 2025-07-25 16:09:29 +08:00
何冠峰
9cd50bc7f3 fix : 修复构建页面扩展类缺少指定属性报错的问题。 2025-07-25 15:43:37 +08:00
何冠峰
e92505ba88 samples : 增加自定义构建页面的扩展示例 2025-07-25 15:42:17 +08:00
何冠峰
06a670730c Update README.md 2025-07-25 14:50:13 +08:00
何冠峰
ccd21e56cb sample : 更新UniTask扩展库的说明文档 2025-07-24 16:35:22 +08:00
何冠峰
522bcc529a update UniTask sample 2025-07-24 14:56:58 +08:00
何冠峰
2254ac9f5e update UniTask sample
更新说明文档
2025-07-24 14:45:52 +08:00
何冠峰
956b3db71d Merge pull request #601 from GodChouyu/dev
UniTask示例删除UniTask源码,修改为扩展支持。
2025-07-24 11:31:33 +08:00
何冠峰
fb56959c61 style : 统一小游戏编码规范和命名规范 2025-07-24 11:21:37 +08:00
何冠峰
b9b9f4e37d feat : 新增支付宝小游戏文件系统扩展类 2025-07-24 11:18:29 +08:00
GodChouyu
c050d6d172 UniTask示例删除UniTask源码,修改为扩展支持。 2025-07-24 10:15:17 +08:00
何冠峰
baf76a454b Update CHANGELOG.md 2025-07-23 18:49:13 +08:00
何冠峰
385d343262 Update package.json 2025-07-23 18:49:02 +08:00
何冠峰
1f5ad24d44 test : 完善测试用例代码 2025-07-23 18:46:54 +08:00
何冠峰
fefc0043cf fix : 修正小游戏脚本编译错误 2025-07-23 18:46:12 +08:00
422 changed files with 2307 additions and 72602 deletions

View File

@@ -2,7 +2,7 @@
All notable changes to this package will be documented in this file.
## [2.3.13] - 2025-07-23
## [2.3.14] - 2025-07-23
**重要****所有下载相关的超时参数timeout已更新判定逻辑**

View File

@@ -294,6 +294,11 @@ namespace YooAsset.Editor
_scannerListView.itemsSource = filterItems;
_scannerListView.Rebuild();
}
if (_lastModifyScannerIndex >= 0 && _lastModifyScannerIndex < _scannerListView.itemsSource.Count)
{
_scannerListView.selectedIndex = _lastModifyScannerIndex;
}
}
private List<AssetArtScanner> FilterScanners()
{

View File

@@ -77,6 +77,12 @@ namespace YooAsset.Editor
foreach (var classType in viewerClassTypes)
{
var buildPipelineAttribute = EditorTools.GetAttribute<BuildPipelineAttribute>(classType);
if (buildPipelineAttribute == null)
{
Debug.LogWarning($"The class {classType.FullName} need attribute {nameof(BuildPipelineAttribute)}");
continue;
}
string pipelineName = buildPipelineAttribute.PipelineName;
if (_viewClassDic.ContainsKey(pipelineName))
{

View File

@@ -104,7 +104,6 @@ namespace YooAsset.Editor
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, PipelineName);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, PipelineName);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, PipelineName);
var builtinShaderBundleName = GetBuiltinShaderBundleName();
ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
@@ -122,10 +121,10 @@ namespace YooAsset.Editor
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
buildParameters.ManifestProcessServices = CreateManifestProcessServicesInstance();
buildParameters.ManifestRestoreServices = CreateManifestRestoreServicesInstance();
buildParameters.BuiltinShadersBundleName = GetBuiltinShaderBundleName();
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
@@ -143,6 +142,16 @@ namespace YooAsset.Editor
var packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
return packRuleResult.GetBundleName(PackageName, uniqueBundleName);
}
/// <summary>
/// Mono脚本的资源包名称
/// </summary>
protected string GetMonoScriptsBundleName()
{
var uniqueBundleName = AssetBundleCollectorSettingData.Setting.UniqueBundleName;
var packRuleResult = DefaultPackRule.CreateMonosPackRuleResult();
return packRuleResult.GetBundleName(PackageName, uniqueBundleName);
}
}
}
#endif

View File

@@ -17,16 +17,25 @@ namespace YooAsset.Editor
public const string RawFileExtension = "rawfile";
/// <summary>
/// Unity着色器资源包名称
/// 默认的Unity着色器资源包名称
/// </summary>
public const string ShadersBundleName = "unityshaders";
/// <summary>
/// 默认的Unity脚本资源包名称
/// </summary>
public const string MonosBundleName = "unitymonos";
public static PackRuleResult CreateShadersPackRuleResult()
{
PackRuleResult result = new PackRuleResult(ShadersBundleName, AssetBundleFileExtension);
return result;
}
public static PackRuleResult CreateMonosPackRuleResult()
{
PackRuleResult result = new PackRuleResult(MonosBundleName, AssetBundleFileExtension);
return result;
}
}
/// <summary>

View File

@@ -37,6 +37,10 @@ namespace YooAsset
string url;
// 获取对应平台的URL地址
// 说明:苹果不同设备上操作系统不同。
// 说明iPhone和iPod对应的是iOS系统。
// 说明iPad对应的是iPadOS系统。
// 说明AppleTV对应的是tvOS系统。
#if UNITY_EDITOR_OSX
url = StringUtility.Format("file://{0}", path);
#elif UNITY_EDITOR

View File

@@ -335,6 +335,27 @@ namespace YooAsset
#endif
}
/// <summary>
/// 是否属于解压资源包文件
/// </summary>
protected virtual bool IsUnpackBundleFile(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
#if UNITY_ANDROID
if (bundle.Encrypted)
return true;
if (bundle.BundleType == (int)EBuildBundleType.RawBundle)
return true;
return false;
#else
return false;
#endif
}
#region
protected string GetDefaultBuildinPackageRoot(string packageName)
{
@@ -370,27 +391,6 @@ namespace YooAsset
return PathUtility.Combine(_packageRoot, DefaultBuildinFileSystemDefine.BuildinCatalogBinaryFileName);
}
/// <summary>
/// 是否属于解压资源包文件
/// </summary>
protected bool IsUnpackBundleFile(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
#if UNITY_ANDROID
if (bundle.Encrypted)
return true;
if (bundle.BundleType == (int)EBuildBundleType.RawBundle)
return true;
return false;
#else
return false;
#endif
}
/// <summary>
/// 记录文件信息
/// </summary>

View File

@@ -8,14 +8,18 @@ namespace YooAsset
private enum ESteps
{
None,
CopyBuildinManifest,
LoadBuildinPackageVersion,
CopyBuildinPackageHash,
CopyBuildinPackageManifest,
InitUnpackFileSystem,
LoadCatalogFile,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private CopyBuildinPackageManifestOperation _copyBuildinPackageManifestOp;
private RequestBuildinPackageVersionOperation _requestBuildinPackageVersionOp;
private CopyBuildinFileOperation _copyBuildinHashFileOp;
private CopyBuildinFileOperation _copyBuildinManifestFileOp;
private FSInitializeFileSystemOperation _initUnpackFIleSystemOp;
private LoadBuildinCatalogFileOperation _loadBuildinCatalogFileOp;
private ESteps _steps = ESteps.None;
@@ -32,7 +36,7 @@ namespace YooAsset
Error = $"{nameof(DefaultBuildinFileSystem)} is not support WEBGL platform !";
#else
if (_fileSystem.CopyBuildinPackageManifest)
_steps = ESteps.CopyBuildinManifest;
_steps = ESteps.LoadBuildinPackageVersion;
else
_steps = ESteps.InitUnpackFileSystem;
#endif
@@ -42,20 +46,76 @@ namespace YooAsset
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CopyBuildinManifest)
if (_steps == ESteps.LoadBuildinPackageVersion)
{
if (_copyBuildinPackageManifestOp == null)
if (_requestBuildinPackageVersionOp == null)
{
_copyBuildinPackageManifestOp = new CopyBuildinPackageManifestOperation(_fileSystem);
_copyBuildinPackageManifestOp.StartOperation();
AddChildOperation(_copyBuildinPackageManifestOp);
_requestBuildinPackageVersionOp = new RequestBuildinPackageVersionOperation(_fileSystem);
_requestBuildinPackageVersionOp.StartOperation();
AddChildOperation(_requestBuildinPackageVersionOp);
}
_copyBuildinPackageManifestOp.UpdateOperation();
if (_copyBuildinPackageManifestOp.IsDone == false)
_requestBuildinPackageVersionOp.UpdateOperation();
if (_requestBuildinPackageVersionOp.IsDone == false)
return;
if (_copyBuildinPackageManifestOp.Status == EOperationStatus.Succeed)
if (_requestBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CopyBuildinPackageHash;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestBuildinPackageVersionOp.Error;
}
}
if (_steps == ESteps.CopyBuildinPackageHash)
{
if (_copyBuildinHashFileOp == null)
{
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
string destFilePath = GetCopyPackageHashDestPath(packageVersion);
string sourceFilePath = _fileSystem.GetBuildinPackageHashFilePath(packageVersion);
_copyBuildinHashFileOp = new CopyBuildinFileOperation(sourceFilePath, destFilePath);
_copyBuildinHashFileOp.StartOperation();
AddChildOperation(_copyBuildinHashFileOp);
}
_copyBuildinHashFileOp.UpdateOperation();
if (_copyBuildinHashFileOp.IsDone == false)
return;
if (_copyBuildinHashFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CopyBuildinPackageManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _copyBuildinHashFileOp.Error;
}
}
if (_steps == ESteps.CopyBuildinPackageManifest)
{
if (_copyBuildinManifestFileOp == null)
{
string packageVersion = _requestBuildinPackageVersionOp.PackageVersion;
string destFilePath = GetCopyPackageManifestDestPath(packageVersion);
string sourceFilePath = _fileSystem.GetBuildinPackageManifestFilePath(packageVersion);
_copyBuildinManifestFileOp = new CopyBuildinFileOperation(sourceFilePath, destFilePath);
_copyBuildinManifestFileOp.StartOperation();
AddChildOperation(_copyBuildinManifestFileOp);
}
_copyBuildinManifestFileOp.UpdateOperation();
if (_copyBuildinManifestFileOp.IsDone == false)
return;
if (_copyBuildinManifestFileOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.InitUnpackFileSystem;
}
@@ -63,7 +123,7 @@ namespace YooAsset
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _copyBuildinPackageManifestOp.Error;
Error = _copyBuildinManifestFileOp.Error;
}
}
@@ -116,6 +176,30 @@ namespace YooAsset
if (_loadBuildinCatalogFileOp.Status == EOperationStatus.Succeed)
{
var catalog = _loadBuildinCatalogFileOp.Catalog;
if (catalog == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Fatal error : catalog is null !";
return;
}
if (catalog.PackageName != _fileSystem.PackageName)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Catalog file package name {catalog.PackageName} cannot match the file system package name {_fileSystem.PackageName}";
return;
}
foreach (var wrapper in catalog.Wrappers)
{
var fileWrapper = new DefaultBuildinFileSystem.FileWrapper(wrapper.FileName);
_fileSystem.RecordCatalogFile(wrapper.BundleGUID, fileWrapper);
}
YooLogger.Log($"Package '{_fileSystem.PackageName}' buildin catalog files count : {catalog.Wrappers.Count}");
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
@@ -127,5 +211,28 @@ namespace YooAsset
}
}
}
private string GetCopyManifestFileRoot()
{
string destRoot = _fileSystem.CopyBuildinPackageManifestDestRoot;
if (string.IsNullOrEmpty(destRoot))
{
string defaultCacheRoot = YooAssetSettingsData.GetYooDefaultCacheRoot();
destRoot = PathUtility.Combine(defaultCacheRoot, _fileSystem.PackageName, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
}
return destRoot;
}
private string GetCopyPackageHashDestPath(string packageVersion)
{
string fileRoot = GetCopyManifestFileRoot();
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, packageVersion);
return PathUtility.Combine(fileRoot, fileName);
}
private string GetCopyPackageManifestDestPath(string packageVersion)
{
string fileRoot = GetCopyManifestFileRoot();
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, packageVersion);
return PathUtility.Combine(fileRoot, fileName);
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.IO;
namespace YooAsset
{
internal class CopyBuildinFileOperation : AsyncOperationBase
{
private enum ESteps
{
None,
CheckFileExist,
TryCopyFile,
UnpackFile,
Done,
}
private UnityWebFileRequestOperation _webFileRequestOp;
private readonly string _sourceFilePath;
private readonly string _destFilePath;
private ESteps _steps = ESteps.None;
public CopyBuildinFileOperation(string sourceFilePath, string destFilePath)
{
_sourceFilePath = sourceFilePath;
_destFilePath = destFilePath;
}
internal override void InternalStart()
{
_steps = ESteps.CheckFileExist;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CheckFileExist)
{
if (File.Exists(_destFilePath))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.TryCopyFile;
}
}
if (_steps == ESteps.TryCopyFile)
{
if (File.Exists(_sourceFilePath))
{
try
{
var directory = Path.GetDirectoryName(_destFilePath);
if (Directory.Exists(directory) == false)
Directory.CreateDirectory(directory);
File.Copy(_sourceFilePath, _destFilePath, true);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
catch (Exception ex)
{
YooLogger.Warning($"Failed copy buildin file : {ex.Message}");
_steps = ESteps.UnpackFile;
}
}
else
{
_steps = ESteps.UnpackFile;
}
}
if (_steps == ESteps.UnpackFile)
{
if (_webFileRequestOp == null)
{
string url = DownloadSystemHelper.ConvertToWWWPath(_sourceFilePath);
_webFileRequestOp = new UnityWebFileRequestOperation(url, _destFilePath, 60);
_webFileRequestOp.StartOperation();
AddChildOperation(_webFileRequestOp);
}
_webFileRequestOp.UpdateOperation();
if (_webFileRequestOp.IsDone == false)
return;
if (_webFileRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webFileRequestOp.Error;
}
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 40ef2e46f900131419e869398a8d3c9d
guid: bf44368bc5c2bf1479c36d82e931c295
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,173 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
namespace YooAsset
{
internal class CopyBuildinPackageManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageVersion,
CheckHashFile,
UnpackHashFile,
CheckManifestFile,
UnpackManifestFile,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private RequestBuildinPackageVersionOperation _requestBuildinPackageVersionOp;
private UnityWebFileRequestOperation _hashWebFileRequestOp;
private UnityWebFileRequestOperation _manifestWebFileRequestOp;
private string _buildinPackageVersion;
private ESteps _steps = ESteps.None;
public CopyBuildinPackageManifestOperation(DefaultBuildinFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalStart()
{
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageVersion)
{
if (_requestBuildinPackageVersionOp == null)
{
_requestBuildinPackageVersionOp = new RequestBuildinPackageVersionOperation(_fileSystem);
_requestBuildinPackageVersionOp.StartOperation();
AddChildOperation(_requestBuildinPackageVersionOp);
}
_requestBuildinPackageVersionOp.UpdateOperation();
if (_requestBuildinPackageVersionOp.IsDone == false)
return;
if (_requestBuildinPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CheckHashFile;
_buildinPackageVersion = _requestBuildinPackageVersionOp.PackageVersion;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestBuildinPackageVersionOp.Error;
}
}
if (_steps == ESteps.CheckHashFile)
{
string hashFilePath = GetCopyPackageHashDestPath(_buildinPackageVersion);
if (File.Exists(hashFilePath))
{
_steps = ESteps.CheckManifestFile;
return;
}
_steps = ESteps.UnpackHashFile;
}
if (_steps == ESteps.UnpackHashFile)
{
if (_hashWebFileRequestOp == null)
{
string sourcePath = _fileSystem.GetBuildinPackageHashFilePath(_buildinPackageVersion);
string destPath = GetCopyPackageHashDestPath(_buildinPackageVersion);
string url = DownloadSystemHelper.ConvertToWWWPath(sourcePath);
_hashWebFileRequestOp = new UnityWebFileRequestOperation(url, destPath, 60);
_hashWebFileRequestOp.StartOperation();
AddChildOperation(_hashWebFileRequestOp);
}
_hashWebFileRequestOp.UpdateOperation();
if (_hashWebFileRequestOp.IsDone == false)
return;
if (_hashWebFileRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.CheckManifestFile;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _hashWebFileRequestOp.Error;
}
}
if (_steps == ESteps.CheckManifestFile)
{
string manifestFilePath = GetCopyPackageManifestDestPath(_buildinPackageVersion);
if (File.Exists(manifestFilePath))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
return;
}
_steps = ESteps.UnpackManifestFile;
}
if (_steps == ESteps.UnpackManifestFile)
{
if (_manifestWebFileRequestOp == null)
{
string sourcePath = _fileSystem.GetBuildinPackageManifestFilePath(_buildinPackageVersion);
string destPath = GetCopyPackageManifestDestPath(_buildinPackageVersion);
string url = DownloadSystemHelper.ConvertToWWWPath(sourcePath);
_manifestWebFileRequestOp = new UnityWebFileRequestOperation(url, destPath, 60);
_manifestWebFileRequestOp.StartOperation();
AddChildOperation(_manifestWebFileRequestOp);
}
_manifestWebFileRequestOp.UpdateOperation();
if (_manifestWebFileRequestOp.IsDone == false)
return;
if (_manifestWebFileRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _manifestWebFileRequestOp.Error;
}
}
}
private string GetCopyManifestFileRoot()
{
string destRoot = _fileSystem.CopyBuildinPackageManifestDestRoot;
if (string.IsNullOrEmpty(destRoot))
{
string defaultCacheRoot = YooAssetSettingsData.GetYooDefaultCacheRoot();
destRoot = PathUtility.Combine(defaultCacheRoot, _fileSystem.PackageName, DefaultCacheFileSystemDefine.ManifestFilesFolderName);
}
return destRoot;
}
private string GetCopyPackageHashDestPath(string packageVersion)
{
string fileRoot = GetCopyManifestFileRoot();
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, packageVersion);
return PathUtility.Combine(fileRoot, fileName);
}
private string GetCopyPackageManifestDestPath(string packageVersion)
{
string fileRoot = GetCopyManifestFileRoot();
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, packageVersion);
return PathUtility.Combine(fileRoot, fileName);
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
namespace YooAsset
{
@@ -7,29 +8,50 @@ namespace YooAsset
private enum ESteps
{
None,
RequestData,
TryLoadFileData,
RequestFileData,
LoadCatalog,
Done,
}
private readonly DefaultBuildinFileSystem _fileSystem;
private UnityWebDataRequestOperation _webDataRequestOp;
private byte[] _fileData;
private ESteps _steps = ESteps.None;
/// <summary>
/// 内置资源目录
/// </summary>
public DefaultBuildinFileCatalog Catalog;
internal LoadBuildinCatalogFileOperation(DefaultBuildinFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalStart()
{
_steps = ESteps.RequestData;
_steps = ESteps.TryLoadFileData;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestData)
if (_steps == ESteps.TryLoadFileData)
{
string filePath = _fileSystem.GetCatalogBinaryFileLoadPath();
if (File.Exists(filePath))
{
_fileData = File.ReadAllBytes(filePath);
_steps = ESteps.LoadCatalog;
}
else
{
_steps = ESteps.RequestFileData;
}
}
if (_steps == ESteps.RequestFileData)
{
if (_webDataRequestOp == null)
{
@@ -46,6 +68,7 @@ namespace YooAsset
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
{
_fileData = _webDataRequestOp.Result;
_steps = ESteps.LoadCatalog;
}
else
@@ -60,22 +83,7 @@ namespace YooAsset
{
try
{
var catalog = CatalogTools.DeserializeFromBinary(_webDataRequestOp.Result);
if (catalog.PackageName != _fileSystem.PackageName)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Catalog file package name {catalog.PackageName} cannot match the file system package name {_fileSystem.PackageName}";
return;
}
foreach (var wrapper in catalog.Wrappers)
{
var fileWrapper = new DefaultBuildinFileSystem.FileWrapper(wrapper.FileName);
_fileSystem.RecordCatalogFile(wrapper.BundleGUID, fileWrapper);
}
YooLogger.Log($"Package '{_fileSystem.PackageName}' buildin catalog files count : {catalog.Wrappers.Count}");
Catalog = CatalogTools.DeserializeFromBinary(_fileData);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}

View File

@@ -1,4 +1,5 @@

using System.IO;
namespace YooAsset
{
internal class LoadBuildinPackageManifestOperation : AsyncOperationBase
@@ -6,6 +7,7 @@ namespace YooAsset
private enum ESteps
{
None,
TryLoadFileData,
RequestFileData,
VerifyFileData,
LoadManifest,
@@ -17,6 +19,7 @@ namespace YooAsset
private readonly string _packageHash;
private UnityWebDataRequestOperation _webDataRequestOp;
private DeserializeManifestOperation _deserializer;
private byte[] _fileData;
private ESteps _steps = ESteps.None;
/// <summary>
@@ -33,13 +36,27 @@ namespace YooAsset
}
internal override void InternalStart()
{
_steps = ESteps.RequestFileData;
_steps = ESteps.TryLoadFileData;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.TryLoadFileData)
{
string filePath = _fileSystem.GetBuildinPackageManifestFilePath(_packageVersion);
if (File.Exists(filePath))
{
_fileData = File.ReadAllBytes(filePath);
_steps = ESteps.VerifyFileData;
}
else
{
_steps = ESteps.RequestFileData;
}
}
if (_steps == ESteps.RequestFileData)
{
if (_webDataRequestOp == null)
@@ -57,6 +74,7 @@ namespace YooAsset
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
{
_fileData = _webDataRequestOp.Result;
_steps = ESteps.VerifyFileData;
}
else
@@ -69,7 +87,7 @@ namespace YooAsset
if (_steps == ESteps.VerifyFileData)
{
if (ManifestTools.VerifyManifestData(_webDataRequestOp.Result, _packageHash))
if (ManifestTools.VerifyManifestData(_fileData, _packageHash))
{
_steps = ESteps.LoadManifest;
}
@@ -85,7 +103,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _fileData);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -1,4 +1,5 @@

using System.IO;
namespace YooAsset
{
internal class RequestBuildinPackageHashOperation : AsyncOperationBase
@@ -6,7 +7,9 @@ namespace YooAsset
private enum ESteps
{
None,
TryLoadPackageHash,
RequestPackageHash,
CheckResult,
Done,
}
@@ -28,13 +31,27 @@ namespace YooAsset
}
internal override void InternalStart()
{
_steps = ESteps.RequestPackageHash;
_steps = ESteps.TryLoadPackageHash;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.TryLoadPackageHash)
{
string filePath = _fileSystem.GetBuildinPackageHashFilePath(_packageVersion);
if (File.Exists(filePath))
{
PackageHash = File.ReadAllText(filePath);
_steps = ESteps.CheckResult;
}
else
{
_steps = ESteps.RequestPackageHash;
}
}
if (_steps == ESteps.RequestPackageHash)
{
if (_webTextRequestOp == null)
@@ -53,17 +70,7 @@ namespace YooAsset
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageHash = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
_steps = ESteps.CheckResult;
}
else
{
@@ -72,6 +79,21 @@ namespace YooAsset
Error = _webTextRequestOp.Error;
}
}
if (_steps == ESteps.CheckResult)
{
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
}

View File

@@ -1,4 +1,5 @@

using System.IO;
namespace YooAsset
{
internal class RequestBuildinPackageVersionOperation : AsyncOperationBase
@@ -6,7 +7,9 @@ namespace YooAsset
private enum ESteps
{
None,
TryLoadPackageVersion,
RequestPackageVersion,
CheckResult,
Done,
}
@@ -26,13 +29,27 @@ namespace YooAsset
}
internal override void InternalStart()
{
_steps = ESteps.RequestPackageVersion;
_steps = ESteps.TryLoadPackageVersion;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.TryLoadPackageVersion)
{
string filePath = _fileSystem.GetBuildinPackageVersionFilePath();
if (File.Exists(filePath))
{
PackageVersion = File.ReadAllText(filePath);
_steps = ESteps.CheckResult;
}
else
{
_steps = ESteps.RequestPackageVersion;
}
}
if (_steps == ESteps.RequestPackageVersion)
{
if (_webTextRequestOp == null)
@@ -51,17 +68,7 @@ namespace YooAsset
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
_steps = ESteps.CheckResult;
}
else
{
@@ -70,6 +77,21 @@ namespace YooAsset
Error = _webTextRequestOp.Error;
}
}
if (_steps == ESteps.CheckResult)
{
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Buildin package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
}
}
}

View File

@@ -33,6 +33,7 @@ namespace YooAsset
{
get
{
// NOTE : 单次调用开销约1微秒
return _watch.ElapsedMilliseconds - _frameTime >= MaxTimeSlice;
}
}
@@ -82,10 +83,11 @@ namespace YooAsset
}
// 更新进行中的异步操作
bool checkBusy = MaxTimeSlice < long.MaxValue;
_frameTime = _watch.ElapsedMilliseconds;
for (int i = 0; i < _operations.Count; i++)
{
if (IsBusy)
if (checkBusy && IsBusy)
break;
var operation = _operations[i];

View File

@@ -251,7 +251,7 @@ namespace YooAsset
/// 预下载指定版本的包裹资源
/// </summary>
/// <param name="packageVersion">包裹版本</param>
/// <param name="timeout">超时时间默认值60秒</param>
/// <param name="timeout">资源清单下载的超时时间默认值60秒</param>
public PreDownloadContentOperation PreDownloadContentAsync(string packageVersion, int timeout = 60)
{
DebugCheckInitialize(false);

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 64b064347ca7a404494a996b072e2e29
guid: f450f29c62aedae4390edc923f71811d
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,92 @@
using System.IO;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
public class CreateBuildinCatalogWindow : EditorWindow
{
static CreateBuildinCatalogWindow _thisInstance;
[MenuItem("Tools/内置清单生成工具Catalog", false, 101)]
static void ShowWindow()
{
if (_thisInstance == null)
{
_thisInstance = EditorWindow.GetWindow(typeof(CreateBuildinCatalogWindow), false, "内置清单生成工具", true) as CreateBuildinCatalogWindow;
_thisInstance.minSize = new Vector2(800, 600);
}
_thisInstance.Show();
}
private string _directoryRoot = string.Empty;
private void OnGUI()
{
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择内置资源目录", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFolderPanel("Find", "Assets/", "StreamingAssets");
if (!string.IsNullOrEmpty(resultPath))
_directoryRoot = resultPath;
}
EditorGUILayout.LabelField(_directoryRoot);
EditorGUILayout.EndHorizontal();
if (string.IsNullOrEmpty(_directoryRoot) == false)
{
if (GUILayout.Button("生成Catalog文件", GUILayout.MaxWidth(150)))
{
CreateCatalogFile(_directoryRoot);
}
}
}
private void CreateCatalogFile(string directoryRoot)
{
// 搜索所有Package目录
List<string> packageRoots = GetPackageRoots(directoryRoot);
foreach (var packageRoot in packageRoots)
{
DirectoryInfo directoryInfo = new DirectoryInfo(packageRoot);
string packageName = directoryInfo.Name;
try
{
bool result = CatalogTools.CreateCatalogFile(null, packageName, packageRoot); //TODO 自行处理解密
if (result == false)
{
Debug.LogError($"Create package {packageName} catalog file failed ! See the detail error in console !");
}
}
catch (System.Exception ex)
{
Debug.LogError($"Create package {packageName} catalog file failed ! {ex.Message}");
}
}
}
private List<string> GetPackageRoots(string rootPath)
{
// 检查目录是否存在
if (Directory.Exists(rootPath) == false)
{
throw new DirectoryNotFoundException($"目录不存在: {rootPath}");
}
// 搜索所有 .version 文件(包含子目录)
string[] versionFiles = Directory.GetFiles(
rootPath,
"*.version",
SearchOption.AllDirectories
);
// 提取文件所在目录路径并去重
return versionFiles
.Select(file => Path.GetDirectoryName(file))
.Distinct()
.ToList();
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 69f62f6b4185d06498f96aa272e9b926
guid: 16ab831593388974fa7e8f8c7e8199a8
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a5b9231662e24c942b544bd85d4b39cb
guid: e8f5ca9e913008d4988fe0f4a2f4a443
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,18 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
using YooAsset.Editor;
[BuildPipelineAttribute("CustomBuildPipeline")]
internal class CustomBuildPipelineViewer : BuiltinBuildPipelineViewer
{
protected override string GetDefaultPackageVersion()
{
return "v1.0.0";
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 52e2d973a2156674e8c1c9433ed031f7
guid: e721201eb2cad4e4ca207b9c99208055
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 275b87293edc6634f9d72387851dbbdf
guid: 7d2280a83472bd14bb033f506647284d
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,280 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using System;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
using AlipaySdk;
public static class AlipayFileSystemCreater
{
public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteServices remoteServices)
{
string fileSystemClass = $"{nameof(AlipayFileSystem)},YooAsset.MiniGame";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
return fileSystemParams;
}
public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteServices remoteServices, IWebDecryptionServices decryptionServices)
{
string fileSystemClass = $"{nameof(AlipayFileSystem)},YooAsset.MiniGame";
var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
fileSystemParams.AddParameter(FileSystemParametersDefine.REMOTE_SERVICES, remoteServices);
fileSystemParams.AddParameter(FileSystemParametersDefine.DECRYPTION_SERVICES, decryptionServices);
return fileSystemParams;
}
}
/// <summary>
/// 支付宝小游戏文件系统
/// 参考https://opendocs.alipay.com/mini-game/0ftleg
/// </summary>
internal class AlipayFileSystem : IFileSystem
{
private class WebRemoteServices : IRemoteServices
{
private readonly string _webPackageRoot;
protected readonly Dictionary<string, string> _mapping = new Dictionary<string, string>(10000);
public WebRemoteServices(string buildinPackRoot)
{
_webPackageRoot = buildinPackRoot;
}
string IRemoteServices.GetRemoteMainURL(string fileName)
{
return GetFileLoadURL(fileName);
}
string IRemoteServices.GetRemoteFallbackURL(string fileName)
{
return GetFileLoadURL(fileName);
}
private string GetFileLoadURL(string fileName)
{
if (_mapping.TryGetValue(fileName, out string url) == false)
{
string filePath = PathUtility.Combine(_webPackageRoot, fileName);
url = DownloadSystemHelper.ConvertToWWWPath(filePath);
_mapping.Add(fileName, url);
}
return url;
}
}
private readonly Dictionary<string, string> _cacheFilePathMapping = new Dictionary<string, string>(10000);
private AlipayFSManager _fileSystemMgr;
private string _aliCacheRoot = string.Empty;
/// <summary>
/// 包裹名称
/// </summary>
public string PackageName { private set; get; }
/// <summary>
/// 文件根目录
/// </summary>
public string FileRoot
{
get
{
return _aliCacheRoot;
}
}
/// <summary>
/// 文件数量
/// </summary>
public int FileCount
{
get
{
return 0;
}
}
#region
/// <summary>
/// 自定义参数:远程服务接口
/// </summary>
public IRemoteServices RemoteServices { private set; get; } = null;
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestRestoreServices ManifestServices { private set; get; }
#endregion
public AlipayFileSystem()
{
}
public virtual FSInitializeFileSystemOperation InitializeFileSystemAsync()
{
var operation = new APFSInitializeOperation(this);
return operation;
}
public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout)
{
var operation = new APFSLoadPackageManifestOperation(this, packageVersion, timeout);
return operation;
}
public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout)
{
var operation = new APFSRequestPackageVersionOperation(this, appendTimeTicks, timeout);
return operation;
}
public virtual FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, ClearCacheFilesOptions options)
{
var operation = new FSClearCacheFilesCompleteOperation();
return operation;
}
public virtual FSDownloadFileOperation DownloadFileAsync(PackageBundle bundle, DownloadFileOptions options)
{
string mainURL = RemoteServices.GetRemoteMainURL(bundle.FileName);
string fallbackURL = RemoteServices.GetRemoteFallbackURL(bundle.FileName);
options.SetURL(mainURL, fallbackURL);
var operation = new APFSDownloadFileOperation(this, bundle, options);
return operation;
}
public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
{
if (bundle.BundleType == (int)EBuildBundleType.AssetBundle)
{
var operation = new APFSLoadBundleOperation(this, bundle);
return operation;
}
else
{
string error = $"{nameof(AlipayFileSystem)} not support load bundle type : {bundle.BundleType}";
var operation = new FSLoadBundleCompleteOperation(error);
return operation;
}
}
public virtual void SetParameter(string name, object value)
{
if (name == FileSystemParametersDefine.REMOTE_SERVICES)
{
RemoteServices = (IRemoteServices)value;
}
else if (name == FileSystemParametersDefine.DECRYPTION_SERVICES)
{
DecryptionServices = (IWebDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestRestoreServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");
}
}
public virtual void OnCreate(string packageName, string rootDirectory)
{
PackageName = packageName;
_aliCacheRoot = rootDirectory;
if (string.IsNullOrEmpty(_aliCacheRoot))
{
throw new System.Exception("请配置支付宝小游戏的缓存根目录!");
}
// 注意CDN服务未启用的情况下使用支付宝WEB服务器
if (RemoteServices == null)
{
string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetSettingsData.Setting.DefaultYooFolderName, packageName);
RemoteServices = new WebRemoteServices(webRoot);
}
_fileSystemMgr = AlipaySDK.API.GetFileSystemManager();
}
public virtual void OnDestroy()
{
}
public virtual bool Belong(PackageBundle bundle)
{
return true;
}
public virtual bool Exists(PackageBundle bundle)
{
return CheckCacheFileExist(bundle);
}
public virtual bool NeedDownload(PackageBundle bundle)
{
if (Belong(bundle) == false)
return false;
return Exists(bundle) == false;
}
public virtual bool NeedUnpack(PackageBundle bundle)
{
return false;
}
public virtual bool NeedImport(PackageBundle bundle)
{
return false;
}
public virtual string GetBundleFilePath(PackageBundle bundle)
{
return GetCacheFileLoadPath(bundle);
}
public virtual byte[] ReadBundleFileData(PackageBundle bundle)
{
if (CheckCacheFileExist(bundle))
{
string filePath = GetCacheFileLoadPath(bundle);
return _fileSystemMgr.ReadFileSync(filePath);
}
else
{
return Array.Empty<byte>();
}
}
public virtual string ReadBundleFileText(PackageBundle bundle)
{
if (CheckCacheFileExist(bundle))
{
string filePath = GetCacheFileLoadPath(bundle);
return _fileSystemMgr.ReadFileSync(filePath, "utf8");
}
else
{
return string.Empty;
}
}
#region
public AlipayFSManager GetFileSystemMgr()
{
return _fileSystemMgr;
}
public bool CheckCacheFileExist(PackageBundle bundle)
{
//TODO : 效率极低
/*
string filePath = GetCacheFileLoadPath(bundle);
string result = _fileSystemMgr.AccessSync(filePath);
return result.Equals("access:ok", StringComparison.Ordinal);
*/
return false;
}
private string GetCacheFileLoadPath(PackageBundle bundle)
{
if (_cacheFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{
filePath = PathUtility.Combine(_aliCacheRoot, bundle.FileName);
_cacheFilePathMapping.Add(bundle.BundleGUID, filePath);
}
return filePath;
}
#endregion
}
#endif

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 5bee3e3860e37484aa3b861bf76d129f
guid: 61be9965c7f7aae468a34b3ed38116b5
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 25cb2f742bfeb1d48a4e65d3140b955d
guid: 44b9746ed3270394eb54d85b27a2ef04
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,67 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
using AlipaySdk;
namespace YooAsset
{
internal class APAssetBundleResult : BundleResult
{
private readonly IFileSystem _fileSystem;
private readonly PackageBundle _packageBundle;
private readonly AssetBundle _assetBundle;
public APAssetBundleResult(IFileSystem fileSystem, PackageBundle packageBundle, AssetBundle assetBundle)
{
_fileSystem = fileSystem;
_packageBundle = packageBundle;
_assetBundle = assetBundle;
}
public override void UnloadBundleFile()
{
if (_assetBundle != null)
{
if (_packageBundle.Encrypted)
_assetBundle.Unload(true);
else
_assetBundle.APUnload(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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1de437726bd89584da56aaddfdb1a07c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 18ae5147de9585045ab40941d945696b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using UnityEngine;
using YooAsset;
internal class APFSDownloadFileOperation : FSDownloadFileOperation
{
protected enum ESteps
{
None,
CreateRequest,
CheckRequest,
TryAgain,
Done,
}
private readonly AlipayFileSystem _fileSystem;
private readonly DownloadFileOptions _options;
private UnityWebCacheRequestOperation _webCacheRequestOp;
private int _requestCount = 0;
private float _tryAgainTimer;
private int _failedTryAgain;
private ESteps _steps = ESteps.None;
internal APFSDownloadFileOperation(AlipayFileSystem fileSystem, PackageBundle bundle, DownloadFileOptions options) : base(bundle)
{
_fileSystem = fileSystem;
_options = options;
}
internal override void InternalStart()
{
_steps = ESteps.CreateRequest;
}
internal override void InternalUpdate()
{
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
string url = GetRequestURL();
_webCacheRequestOp = new UnityWebCacheRequestOperation(url);
_webCacheRequestOp.StartOperation();
AddChildOperation(_webCacheRequestOp);
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
_webCacheRequestOp.UpdateOperation();
Progress = _webCacheRequestOp.Progress;
DownloadProgress = _webCacheRequestOp.DownloadProgress;
DownloadedBytes = _webCacheRequestOp.DownloadedBytes;
if (_webCacheRequestOp.IsDone == false)
return;
if (_webCacheRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
//TODO 需要验证插件请求器的下载进度
DownloadProgress = 1f;
DownloadedBytes = Bundle.FileSize;
Progress = 1f;
}
else
{
if (_failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
YooLogger.Warning($"Failed download : {_webCacheRequestOp.URL} Try again !");
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webCacheRequestOp.Error;
YooLogger.Error(Error);
}
}
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_tryAgainTimer = 0f;
_failedTryAgain--;
Progress = 0f;
DownloadProgress = 0f;
DownloadedBytes = 0;
_steps = ESteps.CreateRequest;
}
}
}
/// <summary>
/// 获取网络请求地址
/// </summary>
private string GetRequestURL()
{
// 轮流返回请求地址
_requestCount++;
if (_requestCount % 2 == 0)
return _options.FallbackURL;
else
return _options.MainURL;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc47317a416e9f542b7ec6b77485a8b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using YooAsset;
internal partial class APFSInitializeOperation : FSInitializeFileSystemOperation
{
private readonly AlipayFileSystem _fileSystem;
public APFSInitializeOperation(AlipayFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
internal override void InternalStart()
{
Status = EOperationStatus.Succeed;
}
internal override void InternalUpdate()
{
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71a99a94d7563fe4a9d56ea0e15aa8d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,88 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using YooAsset;
internal class APFSLoadBundleOperation : FSLoadBundleOperation
{
private enum ESteps
{
None,
LoadAssetBundle,
Done,
}
private readonly AlipayFileSystem _fileSystem;
private readonly PackageBundle _bundle;
private LoadWebAssetBundleOperation _loadWebAssetBundleOp;
private ESteps _steps = ESteps.None;
internal APFSLoadBundleOperation(AlipayFileSystem fileSystem, PackageBundle bundle)
{
_fileSystem = fileSystem;
_bundle = bundle;
}
internal override void InternalStart()
{
_steps = ESteps.LoadAssetBundle;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadAssetBundle)
{
if (_loadWebAssetBundleOp == null)
{
string mainURL = _fileSystem.RemoteServices.GetRemoteMainURL(_bundle.FileName);
string fallbackURL = _fileSystem.RemoteServices.GetRemoteFallbackURL(_bundle.FileName);
DownloadFileOptions options = new DownloadFileOptions(int.MaxValue);
options.SetURL(mainURL, fallbackURL);
if (_bundle.Encrypted)
{
_loadWebAssetBundleOp = new LoadWebEncryptAssetBundleOperation(_bundle, options, _fileSystem.DecryptionServices);
_loadWebAssetBundleOp.StartOperation();
AddChildOperation(_loadWebAssetBundleOp);
}
else
{
_loadWebAssetBundleOp = new LoadAlipayAssetBundleOperation(_bundle, options);
_loadWebAssetBundleOp.StartOperation();
AddChildOperation(_loadWebAssetBundleOp);
}
}
_loadWebAssetBundleOp.UpdateOperation();
Progress = _loadWebAssetBundleOp.Progress;
DownloadProgress = _loadWebAssetBundleOp.DownloadProgress;
DownloadedBytes = _loadWebAssetBundleOp.DownloadedBytes;
if (_loadWebAssetBundleOp.IsDone == false)
return;
if (_loadWebAssetBundleOp.Status == EOperationStatus.Succeed)
{
var assetBundle = _loadWebAssetBundleOp.Result;
_steps = ESteps.Done;
Result = new APAssetBundleResult(_fileSystem, _bundle, assetBundle);
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _loadWebAssetBundleOp.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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f71fc4fc468d41441b00be64938b2fe9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using YooAsset;
internal class APFSLoadPackageManifestOperation : FSLoadPackageManifestOperation
{
private enum ESteps
{
None,
RequestPackageHash,
LoadPackageManifest,
Done,
}
private readonly AlipayFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly int _timeout;
private RequestAlipayPackageHashOperation _requestPackageHashOp;
private LoadAlipayPackageManifestOperation _loadPackageManifestOp;
private ESteps _steps = ESteps.None;
public APFSLoadPackageManifestOperation(AlipayFileSystem 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 RequestAlipayPackageHashOperation(_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 LoadAlipayPackageManifestOperation(_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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 335885fb4e1977a4ca5c26263eda03d7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using YooAsset;
internal class APFSRequestPackageVersionOperation : FSRequestPackageVersionOperation
{
private enum ESteps
{
None,
RequestPackageVersion,
Done,
}
private readonly AlipayFileSystem _fileSystem;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private RequestAlipayPackageVersionOperation _requestWebPackageVersionOp;
private ESteps _steps = ESteps.None;
internal APFSRequestPackageVersionOperation(AlipayFileSystem fileSystem, bool appendTimeTicks, int timeout)
{
_fileSystem = fileSystem;
_appendTimeTicks = appendTimeTicks;
_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 (_requestWebPackageVersionOp == null)
{
_requestWebPackageVersionOp = new RequestAlipayPackageVersionOperation(_fileSystem, _appendTimeTicks, _timeout);
_requestWebPackageVersionOp.StartOperation();
AddChildOperation(_requestWebPackageVersionOp);
}
_requestWebPackageVersionOp.UpdateOperation();
Progress = _requestWebPackageVersionOp.Progress;
if (_requestWebPackageVersionOp.IsDone == false)
return;
if (_requestWebPackageVersionOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
PackageVersion = _requestWebPackageVersionOp.PackageVersion;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _requestWebPackageVersionOp.Error;
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a879fd6a506b37345b4b9ea6c5de20bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b94d7bcfa19151046a1f0ed8e089a474
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using UnityEngine;
using AlipaySdk;
namespace YooAsset
{
internal class LoadAlipayAssetBundleOperation : LoadWebAssetBundleOperation
{
protected enum ESteps
{
None,
CreateRequest,
CheckRequest,
TryAgain,
Done,
}
private readonly PackageBundle _bundle;
private readonly DownloadFileOptions _options;
private UnityAlipayAssetBundleRequestOperation _unityAssetBundleRequestOp;
private int _requestCount = 0;
private float _tryAgainTimer;
private int _failedTryAgain;
private ESteps _steps = ESteps.None;
internal LoadAlipayAssetBundleOperation(PackageBundle bundle, DownloadFileOptions options)
{
_bundle = bundle;
_options = options;
}
internal override void InternalStart()
{
_steps = ESteps.CreateRequest;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
string url = GetRequestURL();
_unityAssetBundleRequestOp = new UnityAlipayAssetBundleRequestOperation(_bundle, url);
_unityAssetBundleRequestOp.StartOperation();
AddChildOperation(_unityAssetBundleRequestOp);
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
_unityAssetBundleRequestOp.UpdateOperation();
Progress = _unityAssetBundleRequestOp.Progress;
DownloadProgress = _unityAssetBundleRequestOp.DownloadProgress;
DownloadedBytes = _unityAssetBundleRequestOp.DownloadedBytes;
if (_unityAssetBundleRequestOp.IsDone == false)
return;
if (_unityAssetBundleRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
Result = _unityAssetBundleRequestOp.Result;
}
else
{
if (_failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
YooLogger.Warning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !");
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _unityAssetBundleRequestOp.Error;
YooLogger.Error(Error);
}
}
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_tryAgainTimer = 0f;
_failedTryAgain--;
Progress = 0f;
DownloadProgress = 0f;
DownloadedBytes = 0;
_steps = ESteps.CreateRequest;
}
}
}
/// <summary>
/// 获取网络请求地址
/// </summary>
private string GetRequestURL()
{
// 轮流返回请求地址
_requestCount++;
if (_requestCount % 2 == 0)
return _options.FallbackURL;
else
return _options.MainURL;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 62249d32580e2ef48a33afb58515312a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using YooAsset;
internal class LoadAlipayPackageManifestOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestFileData,
VerifyFileData,
LoadManifest,
Done,
}
private readonly AlipayFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly string _packageHash;
private readonly int _timeout;
private UnityWebDataRequestOperation _webDataRequestOp;
private DeserializeManifestOperation _deserializer;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹清单
/// </summary>
public PackageManifest Manifest { private set; get; }
internal LoadAlipayPackageManifestOperation(AlipayFileSystem fileSystem, string packageVersion, string packageHash, int timeout)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_packageHash = packageHash;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(LoadAlipayPackageManifestOperation));
_steps = ESteps.RequestFileData;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestFileData)
{
if (_webDataRequestOp == null)
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(_fileSystem.PackageName, _packageVersion);
string url = GetRequestURL(fileName);
_webDataRequestOp = new UnityWebDataRequestOperation(url, _timeout);
_webDataRequestOp.StartOperation();
AddChildOperation(_webDataRequestOp);
}
_webDataRequestOp.UpdateOperation();
Progress = _webDataRequestOp.Progress;
if (_webDataRequestOp.IsDone == false)
return;
if (_webDataRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.VerifyFileData;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webDataRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(LoadAlipayPackageManifestOperation));
}
}
if (_steps == ESteps.VerifyFileData)
{
string fileHash = HashUtility.BytesCRC32(_webDataRequestOp.Result);
if (fileHash == _packageHash)
{
_steps = ESteps.LoadManifest;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = "Failed to verify package manifest file!";
}
}
if (_steps == ESteps.LoadManifest)
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}
_deserializer.UpdateOperation();
Progress = _deserializer.Progress;
if (_deserializer.IsDone == false)
return;
if (_deserializer.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Manifest = _deserializer.Manifest;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _deserializer.Error;
}
}
}
private string GetRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c802e6ad51754e144bb4e08942da9592
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using YooAsset;
internal class RequestAlipayPackageHashOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageHash,
Done,
}
private readonly AlipayFileSystem _fileSystem;
private readonly string _packageVersion;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹哈希值
/// </summary>
public string PackageHash { private set; get; }
public RequestAlipayPackageHashOperation(AlipayFileSystem fileSystem, string packageVersion, int timeout)
{
_fileSystem = fileSystem;
_packageVersion = packageVersion;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(RequestAlipayPackageHashOperation));
_steps = ESteps.RequestPackageHash;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageHash)
{
if (_webTextRequestOp == null)
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(_fileSystem.PackageName, _packageVersion);
string url = GetRequestURL(fileName);
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
_webTextRequestOp.StartOperation();
AddChildOperation(_webTextRequestOp);
}
_webTextRequestOp.UpdateOperation();
Progress = _webTextRequestOp.Progress;
if (_webTextRequestOp.IsDone == false)
return;
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageHash = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageHash))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Web package hash file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(RequestAlipayPackageHashOperation));
}
}
}
private string GetRequestURL(string fileName)
{
// 轮流返回请求地址
if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b4f8cf6fe34a7e419f8e3a0063f591b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,100 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using YooAsset;
internal class RequestAlipayPackageVersionOperation : AsyncOperationBase
{
private enum ESteps
{
None,
RequestPackageVersion,
Done,
}
private readonly AlipayFileSystem _fileSystem;
private readonly bool _appendTimeTicks;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp;
private int _requestCount = 0;
private ESteps _steps = ESteps.None;
/// <summary>
/// 包裹版本
/// </summary>
public string PackageVersion { private set; get; }
public RequestAlipayPackageVersionOperation(AlipayFileSystem fileSystem, bool appendTimeTicks, int timeout)
{
_fileSystem = fileSystem;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout;
}
internal override void InternalStart()
{
_requestCount = WebRequestCounter.GetRequestFailedCount(_fileSystem.PackageName, nameof(RequestAlipayPackageVersionOperation));
_steps = ESteps.RequestPackageVersion;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.RequestPackageVersion)
{
if (_webTextRequestOp == null)
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(_fileSystem.PackageName);
string url = GetRequestURL(fileName);
_webTextRequestOp = new UnityWebTextRequestOperation(url, _timeout);
_webTextRequestOp.StartOperation();
AddChildOperation(_webTextRequestOp);
}
_webTextRequestOp.UpdateOperation();
Progress = _webTextRequestOp.Progress;
if (_webTextRequestOp.IsDone == false)
return;
if (_webTextRequestOp.Status == EOperationStatus.Succeed)
{
PackageVersion = _webTextRequestOp.Result;
if (string.IsNullOrEmpty(PackageVersion))
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Web package version file content is empty !";
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _webTextRequestOp.Error;
WebRequestCounter.RecordRequestFailed(_fileSystem.PackageName, nameof(RequestAlipayPackageVersionOperation));
}
}
}
private string GetRequestURL(string fileName)
{
string url;
// 轮流返回请求地址
if (_requestCount % 2 == 0)
url = _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else
url = _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
// 在URL末尾添加时间戳
if (_appendTimeTicks)
return $"{url}?{System.DateTime.UtcNow.Ticks}";
else
return url;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ef3d88ce51a6fa47be1b157316a740c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
#if UNITY_WEBGL && UNITY_ALIMINIGAME
using UnityEngine.Networking;
using UnityEngine;
using AlipaySdk;
namespace YooAsset
{
internal class UnityAlipayAssetBundleRequestOperation : UnityWebRequestOperation
{
protected enum ESteps
{
None,
CreateRequest,
Download,
Done,
}
private readonly PackageBundle _packageBundle;
private UnityWebRequestAsyncOperation _requestOperation;
private ESteps _steps = ESteps.None;
/// <summary>
/// 请求结果
/// </summary>
public AssetBundle Result { private set; get; }
internal UnityAlipayAssetBundleRequestOperation(PackageBundle bundle, string url) : base(url)
{
_packageBundle = bundle;
}
internal override void InternalStart()
{
_steps = ESteps.CreateRequest;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.CreateRequest)
{
CreateWebRequest();
_steps = ESteps.Download;
}
if (_steps == ESteps.Download)
{
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = _requestOperation.progress;
if (_requestOperation.isDone == false)
return;
if (CheckRequestResult())
{
var downloadHanlder = (DownloadHandlerAPAssetBundle)_webRequest.downloadHandler;
AssetBundle assetBundle = downloadHanlder.assetBundle;
if (assetBundle == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"URL : {_requestURL} Download handler asset bundle object is null !";
}
else
{
_steps = ESteps.Done;
Result = assetBundle;
Status = EOperationStatus.Succeed;
//TODO 需要验证插件请求器的下载进度
DownloadProgress = 1f;
DownloadedBytes = _packageBundle.FileSize;
Progress = 1f;
}
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
}
// 注意:最终释放请求器
DisposeRequest();
}
}
private void CreateWebRequest()
{
_webRequest = APAssetBundle.GetAssetBundle(_requestURL);
_webRequest.disposeDownloadHandlerOnDispose = true;
_requestOperation = _webRequest.SendWebRequest();
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a2e7a4e37ac067f4ba0a43ebea0aa3f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -48,7 +48,7 @@ internal class TTFSDownloadFileOperation : FSDownloadFileOperation
_webCacheRequestOp.UpdateOperation();
Progress = _webCacheRequestOp.Progress;
DownloadProgress = _webCacheRequestOp.DownloadProgress;
DownloadedBytes = (long)_webCacheRequestOp.DownloadedBytes;
DownloadedBytes = _webCacheRequestOp.DownloadedBytes;
if (_webCacheRequestOp.IsDone == false)
return;
@@ -57,7 +57,7 @@ internal class TTFSDownloadFileOperation : FSDownloadFileOperation
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
//TODO 需要验证抖音插件请求器的下载进度
//TODO 需要验证插件请求器的下载进度
DownloadProgress = 1f;
DownloadedBytes = Bundle.FileSize;
Progress = 1f;

View File

@@ -1,5 +1,4 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using UnityEngine;
using YooAsset;
internal class TTFSLoadBundleOperation : FSLoadBundleOperation
@@ -7,7 +6,7 @@ internal class TTFSLoadBundleOperation : FSLoadBundleOperation
private enum ESteps
{
None,
DownloadAssetBundle,
LoadAssetBundle,
Done,
}
@@ -23,14 +22,14 @@ internal class TTFSLoadBundleOperation : FSLoadBundleOperation
}
internal override void InternalStart()
{
_steps = ESteps.DownloadAssetBundle;
_steps = ESteps.LoadAssetBundle;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadAssetBundle)
if (_steps == ESteps.LoadAssetBundle)
{
if (_loadWebAssetBundleOp == null)
{
@@ -56,7 +55,7 @@ internal class TTFSLoadBundleOperation : FSLoadBundleOperation
_loadWebAssetBundleOp.UpdateOperation();
Progress = _loadWebAssetBundleOp.Progress;
DownloadProgress = _loadWebAssetBundleOp.DownloadProgress;
DownloadedBytes = (long)_loadWebAssetBundleOp.DownloadedBytes;
DownloadedBytes = _loadWebAssetBundleOp.DownloadedBytes;
if (_loadWebAssetBundleOp.IsDone == false)
return;

View File

@@ -16,7 +16,7 @@ namespace YooAsset
private readonly PackageBundle _bundle;
private readonly DownloadFileOptions _options;
private UnityTiktokAssetBundleRequestOperation _unityTiktokAssetBundleRequestOp;
private UnityTiktokAssetBundleRequestOperation _unityAssetBundleRequestOp;
private int _requestCount = 0;
private float _tryAgainTimer;
@@ -42,40 +42,40 @@ namespace YooAsset
if (_steps == ESteps.CreateRequest)
{
string url = GetRequestURL();
_unityTiktokAssetBundleRequestOp = new UnityTiktokAssetBundleRequestOperation(_bundle, url);
_unityTiktokAssetBundleRequestOp.StartOperation();
AddChildOperation(_unityTiktokAssetBundleRequestOp);
_unityAssetBundleRequestOp = new UnityTiktokAssetBundleRequestOperation(_bundle, url);
_unityAssetBundleRequestOp.StartOperation();
AddChildOperation(_unityAssetBundleRequestOp);
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
_unityTiktokAssetBundleRequestOp.UpdateOperation();
Progress = _unityTiktokAssetBundleRequestOp.Progress;
DownloadProgress = _unityTiktokAssetBundleRequestOp.DownloadProgress;
DownloadedBytes = (long)_unityTiktokAssetBundleRequestOp.DownloadedBytes;
if (_unityTiktokAssetBundleRequestOp.IsDone == false)
_unityAssetBundleRequestOp.UpdateOperation();
Progress = _unityAssetBundleRequestOp.Progress;
DownloadProgress = _unityAssetBundleRequestOp.DownloadProgress;
DownloadedBytes = _unityAssetBundleRequestOp.DownloadedBytes;
if (_unityAssetBundleRequestOp.IsDone == false)
return;
if (_unityTiktokAssetBundleRequestOp.Status == EOperationStatus.Succeed)
if (_unityAssetBundleRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
Result = _unityTiktokAssetBundleRequestOp.Result;
Result = _unityAssetBundleRequestOp.Result;
}
else
{
if (_failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
YooLogger.Warning($"Failed download : {_unityTiktokAssetBundleRequestOp.URL} Try again !");
YooLogger.Warning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !");
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _unityTiktokAssetBundleRequestOp.Error;
Error = _unityAssetBundleRequestOp.Error;
YooLogger.Error(Error);
}
}

View File

@@ -62,7 +62,7 @@ internal class RequestTiktokPackageHashOperation : AsyncOperationBase
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Wechat package hash file content is empty !";
Error = $"Web package hash file content is empty !";
}
else
{

View File

@@ -62,7 +62,7 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Wechat package version file content is empty !";
Error = $"Web package version file content is empty !";
}
else
{

View File

@@ -67,7 +67,7 @@ namespace YooAsset
Result = assetBundle;
Status = EOperationStatus.Succeed;
//TODO 需要验证抖音插件请求器的下载进度
//TODO 需要验证插件请求器的下载进度
DownloadProgress = 1f;
DownloadedBytes = _packageBundle.FileSize;
Progress = 1f;

View File

@@ -1,10 +1,9 @@
#if UNITY_WEBGL && DOUYINMINIGAME
using System;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
using TTSDK;
using System.Linq;
using System;
public static class TiktokFileSystemCreater
{
@@ -107,7 +106,7 @@ internal class TiktokFileSystem : IFileSystem
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
public IManifestRestoreServices ManifestServices { private set; get; }
#endregion
@@ -169,7 +168,7 @@ internal class TiktokFileSystem : IFileSystem
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
ManifestServices = (IManifestRestoreServices)value;
}
else
{

View File

@@ -49,7 +49,7 @@ internal class WXFSDownloadFileOperation : FSDownloadFileOperation
_webCacheRequestOp.UpdateOperation();
Progress = _webCacheRequestOp.Progress;
DownloadProgress = _webCacheRequestOp.DownloadProgress;
DownloadedBytes = (long)_webCacheRequestOp.DownloadedBytes;
DownloadedBytes = _webCacheRequestOp.DownloadedBytes;
if (_webCacheRequestOp.IsDone == false)
return;

View File

@@ -6,7 +6,7 @@ internal class WXFSLoadBundleOperation : FSLoadBundleOperation
private enum ESteps
{
None,
DownloadAssetBundle,
LoadAssetBundle,
Done,
}
@@ -22,14 +22,14 @@ internal class WXFSLoadBundleOperation : FSLoadBundleOperation
}
internal override void InternalStart()
{
_steps = ESteps.DownloadAssetBundle;
_steps = ESteps.LoadAssetBundle;
}
internal override void InternalUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.DownloadAssetBundle)
if (_steps == ESteps.LoadAssetBundle)
{
if (_loadWebAssetBundleOp == null)
{
@@ -55,7 +55,7 @@ internal class WXFSLoadBundleOperation : FSLoadBundleOperation
_loadWebAssetBundleOp.UpdateOperation();
Progress = _loadWebAssetBundleOp.Progress;
DownloadProgress = _loadWebAssetBundleOp.DownloadProgress;
DownloadedBytes = (long)_loadWebAssetBundleOp.DownloadedBytes;
DownloadedBytes = _loadWebAssetBundleOp.DownloadedBytes;
if (_loadWebAssetBundleOp.IsDone == false)
return;

View File

@@ -16,7 +16,7 @@ namespace YooAsset
private readonly PackageBundle _bundle;
private readonly DownloadFileOptions _options;
private UnityWechatAssetBundleRequestOperation _unityWechatAssetBundleRequestOp;
private UnityWechatAssetBundleRequestOperation _unityAssetBundleRequestOp;
private int _requestCount = 0;
private float _tryAgainTimer;
@@ -42,40 +42,40 @@ namespace YooAsset
if (_steps == ESteps.CreateRequest)
{
string url = GetRequestURL();
_unityWechatAssetBundleRequestOp = new UnityWechatAssetBundleRequestOperation(_bundle, url);
_unityWechatAssetBundleRequestOp.StartOperation();
AddChildOperation(_unityWechatAssetBundleRequestOp);
_unityAssetBundleRequestOp = new UnityWechatAssetBundleRequestOperation(_bundle, url);
_unityAssetBundleRequestOp.StartOperation();
AddChildOperation(_unityAssetBundleRequestOp);
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
_unityWechatAssetBundleRequestOp.UpdateOperation();
Progress = _unityWechatAssetBundleRequestOp.Progress;
DownloadProgress = _unityWechatAssetBundleRequestOp.DownloadProgress;
DownloadedBytes = (long)_unityWechatAssetBundleRequestOp.DownloadedBytes;
if (_unityWechatAssetBundleRequestOp.IsDone == false)
_unityAssetBundleRequestOp.UpdateOperation();
Progress = _unityAssetBundleRequestOp.Progress;
DownloadProgress = _unityAssetBundleRequestOp.DownloadProgress;
DownloadedBytes = _unityAssetBundleRequestOp.DownloadedBytes;
if (_unityAssetBundleRequestOp.IsDone == false)
return;
if (_unityWechatAssetBundleRequestOp.Status == EOperationStatus.Succeed)
if (_unityAssetBundleRequestOp.Status == EOperationStatus.Succeed)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
Result = _unityWechatAssetBundleRequestOp.Result;
Result = _unityAssetBundleRequestOp.Result;
}
else
{
if (_failedTryAgain > 0)
{
_steps = ESteps.TryAgain;
YooLogger.Warning($"Failed download : {_unityWechatAssetBundleRequestOp.URL} Try again !");
YooLogger.Warning($"Failed download : {_unityAssetBundleRequestOp.URL} Try again !");
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _unityWechatAssetBundleRequestOp.Error;
Error = _unityAssetBundleRequestOp.Error;
YooLogger.Error(Error);
}
}

View File

@@ -62,7 +62,7 @@ internal class RequestWechatPackageHashOperation : AsyncOperationBase
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Wechat package hash file content is empty !";
Error = $"Web package hash file content is empty !";
}
else
{

View File

@@ -62,7 +62,7 @@ internal class RequestWechatPackageVersionOperation : AsyncOperationBase
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Wechat package version file content is empty !";
Error = $"Web package version file content is empty !";
}
else
{

View File

@@ -70,8 +70,6 @@ internal class WechatFileSystem : IFileSystem
/// </summary>
public string PackageName { private set; get; }
private readonly string _packageRoot = YooAssetSettingsData.Setting.DefaultYooFolderName;
/// <summary>
/// 文件根目录
/// </summary>
@@ -108,7 +106,7 @@ internal class WechatFileSystem : IFileSystem
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
public IManifestRestoreServices ManifestServices { private set; get; }
#endregion
@@ -184,7 +182,7 @@ internal class WechatFileSystem : IFileSystem
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
ManifestServices = (IManifestRestoreServices)value;
}
else
{

View File

@@ -5,6 +5,7 @@
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:5efd170ecd8084500bed5692932fe14e",
"GUID:bb21d6197862c4c3e863390dec9859a7",
"GUID:870f26a2ffa82429195df0861505c5d5",
"GUID:870f26a2ffa82429195df0861505c5d5"
],
"includePlatforms": [],

View File

@@ -67,7 +67,6 @@ public class TestFileStreamDecryption : IDecryptionServices
{
/// <summary>
/// 同步方式获取解密的资源包对象
/// 注意:加载流对象在资源包对象释放的时候会自动释放
/// </summary>
DecryptResult IDecryptionServices.LoadAssetBundle(DecryptFileInfo fileInfo)
{
@@ -80,7 +79,6 @@ public class TestFileStreamDecryption : IDecryptionServices
/// <summary>
/// 异步方式获取解密的资源包对象
/// 注意:加载流对象在资源包对象释放的时候会自动释放
/// </summary>
DecryptResult IDecryptionServices.LoadAssetBundleAsync(DecryptFileInfo fileInfo)
{
@@ -92,11 +90,17 @@ public class TestFileStreamDecryption : IDecryptionServices
}
/// <summary>
/// 后备方式获取解密的资源包对象
/// 后备方式获取解密的资源包
/// 注意:当正常解密方法失败后,会触发后备加载!
/// 说明建议通过LoadFromMemory()方法加载资源包作为保底机制。
/// </summary>
DecryptResult IDecryptionServices.LoadAssetBundleFallback(DecryptFileInfo fileInfo)
{
return new DecryptResult();
byte[] fileData = File.ReadAllBytes(fileInfo.FileLoadPath);
var assetBundle = AssetBundle.LoadFromMemory(fileData);
DecryptResult decryptResult = new DecryptResult();
decryptResult.Result = assetBundle;
return decryptResult;
}
/// <summary>

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,153 @@
fileFormatVersion: 2
guid: d90b9b066363f08419ff51004479d5b7
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,57 +1,82 @@
# UniTask 扩展
这里为了照顾新手使用,做了一些妥协,有定制需求的需要手动调整一下
## 代码示例
### 代码示例
```csharp
public async UniTask Example(IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update)
using System;
using UnityEngine;
using YooAsset;
using Cysharp.Threading.Tasks;
public class TestTask : MonoBehaviour
{
var handle = YooAssets.LoadAssetAsync<GameObject>("Assets/Res/Prefabs/TestImg.prefab");
await handle.ToUniTask(progress, timing);
var obj = handle.AssetObject as GameObject;
var go = Instantiate(obj, transform);
go.transform.localPosition = Vector3.zero;
go.transform.localScale = Vector3.one;
private async void Start()
{
var assetHandle = YooAssets.LoadAssetAsync<GameObject>("UIHome");
await assetHandle.ToUniTask();
Debug.Log($"{assetHandle.Status}");
}
}
```
## 初学者教程
### 使用教程A
**如果你弄不明白 asmdef 文件到底是啥,就按照下发内容操作**
1. 下载 [UniTask](https://github.com/Cysharp/UniTask) 源码并导入到工程内。
-`Samples/UniTask Sample/UniTask` 文件夹拷入游戏中
- 如果项目有 `asmdef`,则引用 `UniTask``YooAsset`,如果没有,就不用关心这一步
2. 修改UniTask源码
UniTask/Runtime/_InternalVisibleTo.cs
## 项目定制教程
```csharp
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("UniTask.Linq")]
[assembly: InternalsVisibleTo("UniTask.Addressables")]
[assembly: InternalsVisibleTo("UniTask.DOTween")]
[assembly: InternalsVisibleTo("UniTask.TextMeshPro")]
[assembly: InternalsVisibleTo("UniTask.YooAsset")] //增加此行代码
```
- 请去下载 [UniTask](https://github.com/Cysharp/UniTask) 源码
- 注意不要用 `Sample` 里面的 `UniTask` 这个是专门给新手定制的
-`Samples/UniTask Sample/UniTask/Runtime/External/YooAsset` 文件夹拷贝到 `UniTask/Runtime/External/YooAsset`
- 创建 `UniTask.YooAsset.asmdef` 文件
- 添加 `UniTask``YooAsset` 的引用
- 在 UniTask `_InternalVisibleTo.cs` 文件中增加 `[assembly: InternalsVisibleTo("UniTask.YooAsset")]` 后即可使用
3. 拷贝YOO提供的扩展脚本到工程内。
## 有效性检查
YooAssets/Samples/UniTask Sample/UniTask目录
一般使用项目定制时, 会出现如下警告, 这说明项目没有配置正确, 建议使用 **初学者定制的** 版本
4. 添加引擎里的宏定义(在宏定义未生效的情况下)
```
yield BundledSceneProvider is not supported on await IEnumerator or Enumerator. ToUniTaskO, please use ToUniTask MonoBehaviou
coroutine Runner) instead
```
Project Settings --> Player --> Scripting Define Symbols
- 在 IDE 中点击 ToUniTask 跳转代码, 看是否可以正确跳转到 `UniTask/Runtime/External/YooAsset` 文件夹中
- 增加 `handle.ToUniTask(progress, timing)` 参数, 看是否有编译错误
```
UNITASK_YOOASSET_SUPPORT
```
如果不正确, 需要检查业务逻辑的 `asmdef` 是否引用正确, 假设你项目业务逻辑的 `asmdef` 名为 `View.asmdef`, 那么在 `View` 中, 要包含如下引用
5. 重启Unity引擎
- YooAsset
- UniTask
- UniTask.YooAsset
重新打开工程后用上面的代码示例验证,看下是否有编译错误!
如果引用正确, 依然还有报错, 说明定制流程有问题, 请检查定制内容是否正确, 或者使用 **初学者定制的** 版本
### 使用教程B
1. 通过Package导入UniTask插件
2. 拷贝YOO提供的扩展脚本到工程内。
YooAssets/Samples/UniTask Sample/UniTask目录
YooAssets/Samples/UniTask Sample/UniTaskRef目录
3. 添加引擎里的宏定义(在宏定义未生效的情况下)
Project Settings --> Player --> Scripting Define Symbols
```
UNITASK_YOOASSET_SUPPORT
```
4. 重启Unity引擎
重新打开工程后用上面的代码示例验证,看下是否有编译错误!
### 注意事项
- 注意检测程序集引用是否丢失
![image](./README-IMG.png)

View File

@@ -1,62 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Cysharp.Threading.Tasks.Editor
{
// reflection call of UnityEditor.SplitterGUILayout
internal static class SplitterGUILayout
{
static BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
static Lazy<Type> splitterStateType = new Lazy<Type>(() =>
{
var type = typeof(EditorWindow).Assembly.GetTypes().First(x => x.FullName == "UnityEditor.SplitterState");
return type;
});
static Lazy<ConstructorInfo> splitterStateCtor = new Lazy<ConstructorInfo>(() =>
{
var type = splitterStateType.Value;
return type.GetConstructor(flags, null, new Type[] { typeof(float[]), typeof(int[]), typeof(int[]) }, null);
});
static Lazy<Type> splitterGUILayoutType = new Lazy<Type>(() =>
{
var type = typeof(EditorWindow).Assembly.GetTypes().First(x => x.FullName == "UnityEditor.SplitterGUILayout");
return type;
});
static Lazy<MethodInfo> beginVerticalSplit = new Lazy<MethodInfo>(() =>
{
var type = splitterGUILayoutType.Value;
return type.GetMethod("BeginVerticalSplit", flags, null, new Type[] { splitterStateType.Value, typeof(GUILayoutOption[]) }, null);
});
static Lazy<MethodInfo> endVerticalSplit = new Lazy<MethodInfo>(() =>
{
var type = splitterGUILayoutType.Value;
return type.GetMethod("EndVerticalSplit", flags, null, Type.EmptyTypes, null);
});
public static object CreateSplitterState(float[] relativeSizes, int[] minSizes, int[] maxSizes)
{
return splitterStateCtor.Value.Invoke(new object[] { relativeSizes, minSizes, maxSizes });
}
public static void BeginVerticalSplit(object splitterState, params GUILayoutOption[] options)
{
beginVerticalSplit.Value.Invoke(null, new object[] { splitterState, options });
}
public static void EndVerticalSplit()
{
endVerticalSplit.Value.Invoke(null, Type.EmptyTypes);
}
}
}

View File

@@ -1,17 +0,0 @@
{
"name": "UniTask.Editor",
"references": [
"UniTask"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -1,182 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System;
using UnityEditor.IMGUI.Controls;
using Cysharp.Threading.Tasks.Internal;
using System.Text;
using System.Text.RegularExpressions;
namespace Cysharp.Threading.Tasks.Editor
{
public class UniTaskTrackerViewItem : TreeViewItem
{
static Regex removeHref = new Regex("<a href.+>(.+)</a>", RegexOptions.Compiled);
public string TaskType { get; set; }
public string Elapsed { get; set; }
public string Status { get; set; }
string position;
public string Position
{
get { return position; }
set
{
position = value;
PositionFirstLine = GetFirstLine(position);
}
}
public string PositionFirstLine { get; private set; }
static string GetFirstLine(string str)
{
var sb = new StringBuilder();
for (int i = 0; i < str.Length; i++)
{
if (str[i] == '\r' || str[i] == '\n')
{
break;
}
sb.Append(str[i]);
}
return removeHref.Replace(sb.ToString(), "$1");
}
public UniTaskTrackerViewItem(int id) : base(id)
{
}
}
public class UniTaskTrackerTreeView : TreeView
{
const string sortedColumnIndexStateKey = "UniTaskTrackerTreeView_sortedColumnIndex";
public IReadOnlyList<TreeViewItem> CurrentBindingItems;
public UniTaskTrackerTreeView()
: this(new TreeViewState(), new MultiColumnHeader(new MultiColumnHeaderState(new[]
{
new MultiColumnHeaderState.Column() { headerContent = new GUIContent("TaskType"), width = 20},
new MultiColumnHeaderState.Column() { headerContent = new GUIContent("Elapsed"), width = 10},
new MultiColumnHeaderState.Column() { headerContent = new GUIContent("Status"), width = 10},
new MultiColumnHeaderState.Column() { headerContent = new GUIContent("Position")},
})))
{
}
UniTaskTrackerTreeView(TreeViewState state, MultiColumnHeader header)
: base(state, header)
{
rowHeight = 20;
showAlternatingRowBackgrounds = true;
showBorder = true;
header.sortingChanged += Header_sortingChanged;
header.ResizeToFit();
Reload();
header.sortedColumnIndex = SessionState.GetInt(sortedColumnIndexStateKey, 1);
}
public void ReloadAndSort()
{
var currentSelected = this.state.selectedIDs;
Reload();
Header_sortingChanged(this.multiColumnHeader);
this.state.selectedIDs = currentSelected;
}
private void Header_sortingChanged(MultiColumnHeader multiColumnHeader)
{
SessionState.SetInt(sortedColumnIndexStateKey, multiColumnHeader.sortedColumnIndex);
var index = multiColumnHeader.sortedColumnIndex;
var ascending = multiColumnHeader.IsSortedAscending(multiColumnHeader.sortedColumnIndex);
var items = rootItem.children.Cast<UniTaskTrackerViewItem>();
IOrderedEnumerable<UniTaskTrackerViewItem> orderedEnumerable;
switch (index)
{
case 0:
orderedEnumerable = ascending ? items.OrderBy(item => item.TaskType) : items.OrderByDescending(item => item.TaskType);
break;
case 1:
orderedEnumerable = ascending ? items.OrderBy(item => double.Parse(item.Elapsed)) : items.OrderByDescending(item => double.Parse(item.Elapsed));
break;
case 2:
orderedEnumerable = ascending ? items.OrderBy(item => item.Status) : items.OrderByDescending(item => item.Elapsed);
break;
case 3:
orderedEnumerable = ascending ? items.OrderBy(item => item.Position) : items.OrderByDescending(item => item.PositionFirstLine);
break;
default:
throw new ArgumentOutOfRangeException(nameof(index), index, null);
}
CurrentBindingItems = rootItem.children = orderedEnumerable.Cast<TreeViewItem>().ToList();
BuildRows(rootItem);
}
protected override TreeViewItem BuildRoot()
{
var root = new TreeViewItem { depth = -1 };
var children = new List<TreeViewItem>();
TaskTracker.ForEachActiveTask((trackingId, awaiterType, status, created, stackTrace) =>
{
children.Add(new UniTaskTrackerViewItem(trackingId) { TaskType = awaiterType, Status = status.ToString(), Elapsed = (DateTime.UtcNow - created).TotalSeconds.ToString("00.00"), Position = stackTrace });
});
CurrentBindingItems = children;
root.children = CurrentBindingItems as List<TreeViewItem>;
return root;
}
protected override bool CanMultiSelect(TreeViewItem item)
{
return false;
}
protected override void RowGUI(RowGUIArgs args)
{
var item = args.item as UniTaskTrackerViewItem;
for (var visibleColumnIndex = 0; visibleColumnIndex < args.GetNumVisibleColumns(); visibleColumnIndex++)
{
var rect = args.GetCellRect(visibleColumnIndex);
var columnIndex = args.GetColumn(visibleColumnIndex);
var labelStyle = args.selected ? EditorStyles.whiteLabel : EditorStyles.label;
labelStyle.alignment = TextAnchor.MiddleLeft;
switch (columnIndex)
{
case 0:
EditorGUI.LabelField(rect, item.TaskType, labelStyle);
break;
case 1:
EditorGUI.LabelField(rect, item.Elapsed, labelStyle);
break;
case 2:
EditorGUI.LabelField(rect, item.Status, labelStyle);
break;
case 3:
EditorGUI.LabelField(rect, item.PositionFirstLine, labelStyle);
break;
default:
throw new ArgumentOutOfRangeException(nameof(columnIndex), columnIndex, null);
}
}
}
}
}

View File

@@ -1,209 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System;
using UnityEditor.IMGUI.Controls;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Editor
{
public class UniTaskTrackerWindow : EditorWindow
{
static int interval;
static UniTaskTrackerWindow window;
[MenuItem("Window/UniTask Tracker")]
public static void OpenWindow()
{
if (window != null)
{
window.Close();
}
// will called OnEnable(singleton instance will be set).
GetWindow<UniTaskTrackerWindow>("UniTask Tracker").Show();
}
static readonly GUILayoutOption[] EmptyLayoutOption = new GUILayoutOption[0];
UniTaskTrackerTreeView treeView;
object splitterState;
void OnEnable()
{
window = this; // set singleton.
splitterState = SplitterGUILayout.CreateSplitterState(new float[] { 75f, 25f }, new int[] { 32, 32 }, null);
treeView = new UniTaskTrackerTreeView();
TaskTracker.EditorEnableState.EnableAutoReload = EditorPrefs.GetBool(TaskTracker.EnableAutoReloadKey, false);
TaskTracker.EditorEnableState.EnableTracking = EditorPrefs.GetBool(TaskTracker.EnableTrackingKey, false);
TaskTracker.EditorEnableState.EnableStackTrace = EditorPrefs.GetBool(TaskTracker.EnableStackTraceKey, false);
}
void OnGUI()
{
// Head
RenderHeadPanel();
// Splittable
SplitterGUILayout.BeginVerticalSplit(this.splitterState, EmptyLayoutOption);
{
// Column Tabble
RenderTable();
// StackTrace details
RenderDetailsPanel();
}
SplitterGUILayout.EndVerticalSplit();
}
#region HeadPanel
public static bool EnableAutoReload => TaskTracker.EditorEnableState.EnableAutoReload;
public static bool EnableTracking => TaskTracker.EditorEnableState.EnableTracking;
public static bool EnableStackTrace => TaskTracker.EditorEnableState.EnableStackTrace;
static readonly GUIContent EnableAutoReloadHeadContent = EditorGUIUtility.TrTextContent("Enable AutoReload", "Reload automatically.", (Texture)null);
static readonly GUIContent ReloadHeadContent = EditorGUIUtility.TrTextContent("Reload", "Reload View.", (Texture)null);
static readonly GUIContent GCHeadContent = EditorGUIUtility.TrTextContent("GC.Collect", "Invoke GC.Collect.", (Texture)null);
static readonly GUIContent EnableTrackingHeadContent = EditorGUIUtility.TrTextContent("Enable Tracking", "Start to track async/await UniTask. Performance impact: low", (Texture)null);
static readonly GUIContent EnableStackTraceHeadContent = EditorGUIUtility.TrTextContent("Enable StackTrace", "Capture StackTrace when task is started. Performance impact: high", (Texture)null);
// [Enable Tracking] | [Enable StackTrace]
void RenderHeadPanel()
{
EditorGUILayout.BeginVertical(EmptyLayoutOption);
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, EmptyLayoutOption);
if (GUILayout.Toggle(EnableAutoReload, EnableAutoReloadHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableAutoReload)
{
TaskTracker.EditorEnableState.EnableAutoReload = !EnableAutoReload;
}
if (GUILayout.Toggle(EnableTracking, EnableTrackingHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableTracking)
{
TaskTracker.EditorEnableState.EnableTracking = !EnableTracking;
}
if (GUILayout.Toggle(EnableStackTrace, EnableStackTraceHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableStackTrace)
{
TaskTracker.EditorEnableState.EnableStackTrace = !EnableStackTrace;
}
GUILayout.FlexibleSpace();
if (GUILayout.Button(ReloadHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption))
{
TaskTracker.CheckAndResetDirty();
treeView.ReloadAndSort();
Repaint();
}
if (GUILayout.Button(GCHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption))
{
GC.Collect(0);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
#endregion
#region TableColumn
Vector2 tableScroll;
GUIStyle tableListStyle;
void RenderTable()
{
if (tableListStyle == null)
{
tableListStyle = new GUIStyle("CN Box");
tableListStyle.margin.top = 0;
tableListStyle.padding.left = 3;
}
EditorGUILayout.BeginVertical(tableListStyle, EmptyLayoutOption);
this.tableScroll = EditorGUILayout.BeginScrollView(this.tableScroll, new GUILayoutOption[]
{
GUILayout.ExpandWidth(true),
GUILayout.MaxWidth(2000f)
});
var controlRect = EditorGUILayout.GetControlRect(new GUILayoutOption[]
{
GUILayout.ExpandHeight(true),
GUILayout.ExpandWidth(true)
});
treeView?.OnGUI(controlRect);
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
}
private void Update()
{
if (EnableAutoReload)
{
if (interval++ % 120 == 0)
{
if (TaskTracker.CheckAndResetDirty())
{
treeView.ReloadAndSort();
Repaint();
}
}
}
}
#endregion
#region Details
static GUIStyle detailsStyle;
Vector2 detailsScroll;
void RenderDetailsPanel()
{
if (detailsStyle == null)
{
detailsStyle = new GUIStyle("CN Message");
detailsStyle.wordWrap = false;
detailsStyle.stretchHeight = true;
detailsStyle.margin.right = 15;
}
string message = "";
var selected = treeView.state.selectedIDs;
if (selected.Count > 0)
{
var first = selected[0];
var item = treeView.CurrentBindingItems.FirstOrDefault(x => x.id == first) as UniTaskTrackerViewItem;
if (item != null)
{
message = item.Position;
}
}
detailsScroll = EditorGUILayout.BeginScrollView(this.detailsScroll, EmptyLayoutOption);
var vector = detailsStyle.CalcSize(new GUIContent(message));
EditorGUILayout.SelectableLabel(message, detailsStyle, new GUILayoutOption[]
{
GUILayout.ExpandHeight(true),
GUILayout.ExpandWidth(true),
GUILayout.MinWidth(vector.x),
GUILayout.MinHeight(vector.y)
});
EditorGUILayout.EndScrollView();
}
#endregion
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: aa765154468d4b34eb34304100d39e64
guid: 2bbb725df946a6f49afbc3ef104fbd8f
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,245 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks
{
public class AsyncLazy
{
static Action<object> continuation = SetCompletionSource;
Func<UniTask> taskFactory;
UniTaskCompletionSource completionSource;
UniTask.Awaiter awaiter;
object syncLock;
bool initialized;
public AsyncLazy(Func<UniTask> taskFactory)
{
this.taskFactory = taskFactory;
this.completionSource = new UniTaskCompletionSource();
this.syncLock = new object();
this.initialized = false;
}
internal AsyncLazy(UniTask task)
{
this.taskFactory = null;
this.completionSource = new UniTaskCompletionSource();
this.syncLock = null;
this.initialized = true;
var awaiter = task.GetAwaiter();
if (awaiter.IsCompleted)
{
SetCompletionSource(awaiter);
}
else
{
this.awaiter = awaiter;
awaiter.SourceOnCompleted(continuation, this);
}
}
public UniTask Task
{
get
{
EnsureInitialized();
return completionSource.Task;
}
}
public UniTask.Awaiter GetAwaiter() => Task.GetAwaiter();
void EnsureInitialized()
{
if (Volatile.Read(ref initialized))
{
return;
}
EnsureInitializedCore();
}
void EnsureInitializedCore()
{
lock (syncLock)
{
if (!Volatile.Read(ref initialized))
{
var f = Interlocked.Exchange(ref taskFactory, null);
if (f != null)
{
var task = f();
var awaiter = task.GetAwaiter();
if (awaiter.IsCompleted)
{
SetCompletionSource(awaiter);
}
else
{
this.awaiter = awaiter;
awaiter.SourceOnCompleted(continuation, this);
}
Volatile.Write(ref initialized, true);
}
}
}
}
void SetCompletionSource(in UniTask.Awaiter awaiter)
{
try
{
awaiter.GetResult();
completionSource.TrySetResult();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void SetCompletionSource(object state)
{
var self = (AsyncLazy)state;
try
{
self.awaiter.GetResult();
self.completionSource.TrySetResult();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
finally
{
self.awaiter = default;
}
}
}
public class AsyncLazy<T>
{
static Action<object> continuation = SetCompletionSource;
Func<UniTask<T>> taskFactory;
UniTaskCompletionSource<T> completionSource;
UniTask<T>.Awaiter awaiter;
object syncLock;
bool initialized;
public AsyncLazy(Func<UniTask<T>> taskFactory)
{
this.taskFactory = taskFactory;
this.completionSource = new UniTaskCompletionSource<T>();
this.syncLock = new object();
this.initialized = false;
}
internal AsyncLazy(UniTask<T> task)
{
this.taskFactory = null;
this.completionSource = new UniTaskCompletionSource<T>();
this.syncLock = null;
this.initialized = true;
var awaiter = task.GetAwaiter();
if (awaiter.IsCompleted)
{
SetCompletionSource(awaiter);
}
else
{
this.awaiter = awaiter;
awaiter.SourceOnCompleted(continuation, this);
}
}
public UniTask<T> Task
{
get
{
EnsureInitialized();
return completionSource.Task;
}
}
public UniTask<T>.Awaiter GetAwaiter() => Task.GetAwaiter();
void EnsureInitialized()
{
if (Volatile.Read(ref initialized))
{
return;
}
EnsureInitializedCore();
}
void EnsureInitializedCore()
{
lock (syncLock)
{
if (!Volatile.Read(ref initialized))
{
var f = Interlocked.Exchange(ref taskFactory, null);
if (f != null)
{
var task = f();
var awaiter = task.GetAwaiter();
if (awaiter.IsCompleted)
{
SetCompletionSource(awaiter);
}
else
{
this.awaiter = awaiter;
awaiter.SourceOnCompleted(continuation, this);
}
Volatile.Write(ref initialized, true);
}
}
}
}
void SetCompletionSource(in UniTask<T>.Awaiter awaiter)
{
try
{
var result = awaiter.GetResult();
completionSource.TrySetResult(result);
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void SetCompletionSource(object state)
{
var self = (AsyncLazy<T>)state;
try
{
var result = self.awaiter.GetResult();
self.completionSource.TrySetResult(result);
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
finally
{
self.awaiter = default;
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 01d1404ca421466419a7db7340ff5e77
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,644 +0,0 @@
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks
{
public interface IReadOnlyAsyncReactiveProperty<T> : IUniTaskAsyncEnumerable<T>
{
T Value { get; }
IUniTaskAsyncEnumerable<T> WithoutCurrent();
UniTask<T> WaitAsync(CancellationToken cancellationToken = default);
}
public interface IAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>
{
new T Value { get; set; }
}
[Serializable]
public class AsyncReactiveProperty<T> : IAsyncReactiveProperty<T>, IDisposable
{
TriggerEvent<T> triggerEvent;
#if UNITY_2018_3_OR_NEWER
[UnityEngine.SerializeField]
#endif
T latestValue;
public T Value
{
get
{
return latestValue;
}
set
{
this.latestValue = value;
triggerEvent.SetResult(value);
}
}
public AsyncReactiveProperty(T value)
{
this.latestValue = value;
this.triggerEvent = default;
}
public IUniTaskAsyncEnumerable<T> WithoutCurrent()
{
return new WithoutCurrentEnumerable(this);
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
{
return new Enumerator(this, cancellationToken, true);
}
public void Dispose()
{
triggerEvent.SetCompleted();
}
public static implicit operator T(AsyncReactiveProperty<T> value)
{
return value.Value;
}
public override string ToString()
{
if (isValueType) return latestValue.ToString();
return latestValue?.ToString();
}
public UniTask<T> WaitAsync(CancellationToken cancellationToken = default)
{
return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out var token), token);
}
static bool isValueType;
static AsyncReactiveProperty()
{
isValueType = typeof(T).IsValueType;
}
sealed class WaitAsyncSource : IUniTaskSource<T>, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource>
{
static Action<object> cancellationCallback = CancellationCallback;
static TaskPool<WaitAsyncSource> pool;
WaitAsyncSource nextNode;
ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
static WaitAsyncSource()
{
TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size);
}
AsyncReactiveProperty<T> parent;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<T> core;
WaitAsyncSource()
{
}
public static IUniTaskSource<T> Create(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
}
if (!pool.TryPop(out var result))
{
result = new WaitAsyncSource();
}
result.parent = parent;
result.cancellationToken = cancellationToken;
if (cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result);
}
result.parent.triggerEvent.Add(result);
TaskTracker.TrackActiveTask(result, 3);
token = result.core.Version;
return result;
}
bool TryReturn()
{
TaskTracker.RemoveTracking(this);
core.Reset();
cancellationTokenRegistration.Dispose();
cancellationTokenRegistration = default;
parent.triggerEvent.Remove(this);
parent = null;
cancellationToken = default;
return pool.TryPush(this);
}
static void CancellationCallback(object state)
{
var self = (WaitAsyncSource)state;
self.OnCanceled(self.cancellationToken);
}
// IUniTaskSource
public T GetResult(short token)
{
try
{
return core.GetResult(token);
}
finally
{
TryReturn();
}
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
// ITriggerHandler
ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
public void OnCanceled(CancellationToken cancellationToken)
{
core.TrySetCanceled(cancellationToken);
}
public void OnCompleted()
{
// Complete as Cancel.
core.TrySetCanceled(CancellationToken.None);
}
public void OnError(Exception ex)
{
core.TrySetException(ex);
}
public void OnNext(T value)
{
core.TrySetResult(value);
}
}
sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
{
readonly AsyncReactiveProperty<T> parent;
public WithoutCurrentEnumerable(AsyncReactiveProperty<T> parent)
{
this.parent = parent;
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(parent, cancellationToken, false);
}
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, ITriggerHandler<T>
{
static Action<object> cancellationCallback = CancellationCallback;
readonly AsyncReactiveProperty<T> parent;
readonly CancellationToken cancellationToken;
readonly CancellationTokenRegistration cancellationTokenRegistration;
T value;
bool isDisposed;
bool firstCall;
public Enumerator(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, bool publishCurrentValue)
{
this.parent = parent;
this.cancellationToken = cancellationToken;
this.firstCall = publishCurrentValue;
parent.triggerEvent.Add(this);
TaskTracker.TrackActiveTask(this, 3);
if (cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
}
}
public T Current => value;
ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
public UniTask<bool> MoveNextAsync()
{
// raise latest value on first call.
if (firstCall)
{
firstCall = false;
value = parent.Value;
return CompletedTasks.True;
}
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
public UniTask DisposeAsync()
{
if (!isDisposed)
{
isDisposed = true;
TaskTracker.RemoveTracking(this);
completionSource.TrySetCanceled(cancellationToken);
parent.triggerEvent.Remove(this);
}
return default;
}
public void OnNext(T value)
{
this.value = value;
completionSource.TrySetResult(true);
}
public void OnCanceled(CancellationToken cancellationToken)
{
DisposeAsync().Forget();
}
public void OnCompleted()
{
completionSource.TrySetResult(false);
}
public void OnError(Exception ex)
{
completionSource.TrySetException(ex);
}
static void CancellationCallback(object state)
{
var self = (Enumerator)state;
self.DisposeAsync().Forget();
}
}
}
public class ReadOnlyAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>, IDisposable
{
TriggerEvent<T> triggerEvent;
T latestValue;
IUniTaskAsyncEnumerator<T> enumerator;
public T Value
{
get
{
return latestValue;
}
}
public ReadOnlyAsyncReactiveProperty(T initialValue, IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
{
latestValue = initialValue;
ConsumeEnumerator(source, cancellationToken).Forget();
}
public ReadOnlyAsyncReactiveProperty(IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
{
ConsumeEnumerator(source, cancellationToken).Forget();
}
async UniTaskVoid ConsumeEnumerator(IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await enumerator.MoveNextAsync())
{
var value = enumerator.Current;
this.latestValue = value;
triggerEvent.SetResult(value);
}
}
finally
{
await enumerator.DisposeAsync();
enumerator = null;
}
}
public IUniTaskAsyncEnumerable<T> WithoutCurrent()
{
return new WithoutCurrentEnumerable(this);
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
{
return new Enumerator(this, cancellationToken, true);
}
public void Dispose()
{
if (enumerator != null)
{
enumerator.DisposeAsync().Forget();
}
triggerEvent.SetCompleted();
}
public static implicit operator T(ReadOnlyAsyncReactiveProperty<T> value)
{
return value.Value;
}
public override string ToString()
{
if (isValueType) return latestValue.ToString();
return latestValue?.ToString();
}
public UniTask<T> WaitAsync(CancellationToken cancellationToken = default)
{
return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out var token), token);
}
static bool isValueType;
static ReadOnlyAsyncReactiveProperty()
{
isValueType = typeof(T).IsValueType;
}
sealed class WaitAsyncSource : IUniTaskSource<T>, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource>
{
static Action<object> cancellationCallback = CancellationCallback;
static TaskPool<WaitAsyncSource> pool;
WaitAsyncSource nextNode;
ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
static WaitAsyncSource()
{
TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size);
}
ReadOnlyAsyncReactiveProperty<T> parent;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<T> core;
WaitAsyncSource()
{
}
public static IUniTaskSource<T> Create(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
}
if (!pool.TryPop(out var result))
{
result = new WaitAsyncSource();
}
result.parent = parent;
result.cancellationToken = cancellationToken;
if (cancellationToken.CanBeCanceled)
{
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result);
}
result.parent.triggerEvent.Add(result);
TaskTracker.TrackActiveTask(result, 3);
token = result.core.Version;
return result;
}
bool TryReturn()
{
TaskTracker.RemoveTracking(this);
core.Reset();
cancellationTokenRegistration.Dispose();
cancellationTokenRegistration = default;
parent.triggerEvent.Remove(this);
parent = null;
cancellationToken = default;
return pool.TryPush(this);
}
static void CancellationCallback(object state)
{
var self = (WaitAsyncSource)state;
self.OnCanceled(self.cancellationToken);
}
// IUniTaskSource
public T GetResult(short token)
{
try
{
return core.GetResult(token);
}
finally
{
TryReturn();
}
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
// ITriggerHandler
ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
public void OnCanceled(CancellationToken cancellationToken)
{
core.TrySetCanceled(cancellationToken);
}
public void OnCompleted()
{
// Complete as Cancel.
core.TrySetCanceled(CancellationToken.None);
}
public void OnError(Exception ex)
{
core.TrySetException(ex);
}
public void OnNext(T value)
{
core.TrySetResult(value);
}
}
sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
{
readonly ReadOnlyAsyncReactiveProperty<T> parent;
public WithoutCurrentEnumerable(ReadOnlyAsyncReactiveProperty<T> parent)
{
this.parent = parent;
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(parent, cancellationToken, false);
}
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, ITriggerHandler<T>
{
static Action<object> cancellationCallback = CancellationCallback;
readonly ReadOnlyAsyncReactiveProperty<T> parent;
readonly CancellationToken cancellationToken;
readonly CancellationTokenRegistration cancellationTokenRegistration;
T value;
bool isDisposed;
bool firstCall;
public Enumerator(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, bool publishCurrentValue)
{
this.parent = parent;
this.cancellationToken = cancellationToken;
this.firstCall = publishCurrentValue;
parent.triggerEvent.Add(this);
TaskTracker.TrackActiveTask(this, 3);
if (cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
}
}
public T Current => value;
ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
public UniTask<bool> MoveNextAsync()
{
// raise latest value on first call.
if (firstCall)
{
firstCall = false;
value = parent.Value;
return CompletedTasks.True;
}
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
public UniTask DisposeAsync()
{
if (!isDisposed)
{
isDisposed = true;
TaskTracker.RemoveTracking(this);
completionSource.TrySetCanceled(cancellationToken);
parent.triggerEvent.Remove(this);
}
return default;
}
public void OnNext(T value)
{
this.value = value;
completionSource.TrySetResult(true);
}
public void OnCanceled(CancellationToken cancellationToken)
{
DisposeAsync().Forget();
}
public void OnCompleted()
{
completionSource.TrySetResult(false);
}
public void OnError(Exception ex)
{
completionSource.TrySetException(ex);
}
static void CancellationCallback(object state)
{
var self = (Enumerator)state;
self.DisposeAsync().Forget();
}
}
}
public static class StateExtensions
{
public static ReadOnlyAsyncReactiveProperty<T> ToReadOnlyAsyncReactiveProperty<T>(this IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
{
return new ReadOnlyAsyncReactiveProperty<T>(source, cancellationToken);
}
public static ReadOnlyAsyncReactiveProperty<T> ToReadOnlyAsyncReactiveProperty<T>(this IUniTaskAsyncEnumerable<T> source, T initialValue, CancellationToken cancellationToken)
{
return new ReadOnlyAsyncReactiveProperty<T>(initialValue, source, cancellationToken);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 8ef320b87f537ee4fb2282e765dc6166
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,26 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or
using System;
namespace Cysharp.Threading.Tasks
{
public readonly struct AsyncUnit : IEquatable<AsyncUnit>
{
public static readonly AsyncUnit Default = new AsyncUnit();
public override int GetHashCode()
{
return 0;
}
public bool Equals(AsyncUnit other)
{
return true;
}
public override string ToString()
{
return "()";
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4f95ac245430d304bb5128d13b6becc8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,23 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Collections.Generic;
using System.Threading;
namespace Cysharp.Threading.Tasks
{
public class CancellationTokenEqualityComparer : IEqualityComparer<CancellationToken>
{
public static readonly IEqualityComparer<CancellationToken> Default = new CancellationTokenEqualityComparer();
public bool Equals(CancellationToken x, CancellationToken y)
{
return x.Equals(y);
}
public int GetHashCode(CancellationToken obj)
{
return obj.GetHashCode();
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 7d739f510b125b74fa7290ac4335e46e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,182 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Runtime.CompilerServices;
using System.Threading;
namespace Cysharp.Threading.Tasks
{
public static class CancellationTokenExtensions
{
static readonly Action<object> cancellationTokenCallback = Callback;
static readonly Action<object> disposeCallback = DisposeCallback;
public static CancellationToken ToCancellationToken(this UniTask task)
{
var cts = new CancellationTokenSource();
ToCancellationTokenCore(task, cts).Forget();
return cts.Token;
}
public static CancellationToken ToCancellationToken(this UniTask task, CancellationToken linkToken)
{
if (linkToken.IsCancellationRequested)
{
return linkToken;
}
if (!linkToken.CanBeCanceled)
{
return ToCancellationToken(task);
}
var cts = CancellationTokenSource.CreateLinkedTokenSource(linkToken);
ToCancellationTokenCore(task, cts).Forget();
return cts.Token;
}
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task)
{
return ToCancellationToken(task.AsUniTask());
}
public static CancellationToken ToCancellationToken<T>(this UniTask<T> task, CancellationToken linkToken)
{
return ToCancellationToken(task.AsUniTask(), linkToken);
}
static async UniTaskVoid ToCancellationTokenCore(UniTask task, CancellationTokenSource cts)
{
try
{
await task;
}
catch (Exception ex)
{
UniTaskScheduler.PublishUnobservedTaskException(ex);
}
cts.Cancel();
cts.Dispose();
}
public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return (UniTask.FromCanceled(cancellationToken), default(CancellationTokenRegistration));
}
var promise = new UniTaskCompletionSource();
return (promise.Task, cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, promise));
}
static void Callback(object state)
{
var promise = (UniTaskCompletionSource)state;
promise.TrySetResult();
}
public static CancellationTokenAwaitable WaitUntilCanceled(this CancellationToken cancellationToken)
{
return new CancellationTokenAwaitable(cancellationToken);
}
public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action callback)
{
var restoreFlow = false;
if (!ExecutionContext.IsFlowSuppressed())
{
ExecutionContext.SuppressFlow();
restoreFlow = true;
}
try
{
return cancellationToken.Register(callback, false);
}
finally
{
if (restoreFlow)
{
ExecutionContext.RestoreFlow();
}
}
}
public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action<object> callback, object state)
{
var restoreFlow = false;
if (!ExecutionContext.IsFlowSuppressed())
{
ExecutionContext.SuppressFlow();
restoreFlow = true;
}
try
{
return cancellationToken.Register(callback, state, false);
}
finally
{
if (restoreFlow)
{
ExecutionContext.RestoreFlow();
}
}
}
public static CancellationTokenRegistration AddTo(this IDisposable disposable, CancellationToken cancellationToken)
{
return cancellationToken.RegisterWithoutCaptureExecutionContext(disposeCallback, disposable);
}
static void DisposeCallback(object state)
{
var d = (IDisposable)state;
d.Dispose();
}
}
public struct CancellationTokenAwaitable
{
CancellationToken cancellationToken;
public CancellationTokenAwaitable(CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
}
public Awaiter GetAwaiter()
{
return new Awaiter(cancellationToken);
}
public struct Awaiter : ICriticalNotifyCompletion
{
CancellationToken cancellationToken;
public Awaiter(CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
}
public bool IsCompleted => !cancellationToken.CanBeCanceled || cancellationToken.IsCancellationRequested;
public void GetResult()
{
}
public void OnCompleted(Action continuation)
{
UnsafeOnCompleted(continuation);
}
public void UnsafeOnCompleted(Action continuation)
{
cancellationToken.RegisterWithoutCaptureExecutionContext(continuation);
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4be7209f04146bd45ac5ee775a5f7c26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,44 +0,0 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System.Threading;
using UnityEngine;
using Cysharp.Threading.Tasks.Triggers;
using System;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks
{
public static partial class CancellationTokenSourceExtensions
{
readonly static Action<object> CancelCancellationTokenSourceStateDelegate = new Action<object>(CancelCancellationTokenSourceState);
static void CancelCancellationTokenSourceState(object state)
{
var cts = (CancellationTokenSource)state;
cts.Cancel();
}
public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
{
return CancelAfterSlim(cts, TimeSpan.FromMilliseconds(millisecondsDelay), delayType, delayTiming);
}
public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
{
return PlayerLoopTimer.StartNew(delayTimeSpan, false, delayType, delayTiming, cts.Token, CancelCancellationTokenSourceStateDelegate, cts);
}
public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, Component component)
{
RegisterRaiseCancelOnDestroy(cts, component.gameObject);
}
public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, GameObject gameObject)
{
var trigger = gameObject.GetAsyncDestroyTrigger();
trigger.CancellationToken.RegisterWithoutCaptureExecutionContext(CancelCancellationTokenSourceStateDelegate, cts);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 22d85d07f1e70ab42a7a4c25bd65e661
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,450 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading;
namespace Cysharp.Threading.Tasks
{
public static class Channel
{
public static Channel<T> CreateSingleConsumerUnbounded<T>()
{
return new SingleConsumerUnboundedChannel<T>();
}
}
public abstract class Channel<TWrite, TRead>
{
public ChannelReader<TRead> Reader { get; protected set; }
public ChannelWriter<TWrite> Writer { get; protected set; }
public static implicit operator ChannelReader<TRead>(Channel<TWrite, TRead> channel) => channel.Reader;
public static implicit operator ChannelWriter<TWrite>(Channel<TWrite, TRead> channel) => channel.Writer;
}
public abstract class Channel<T> : Channel<T, T>
{
}
public abstract class ChannelReader<T>
{
public abstract bool TryRead(out T item);
public abstract UniTask<bool> WaitToReadAsync(CancellationToken cancellationToken = default(CancellationToken));
public abstract UniTask Completion { get; }
public virtual UniTask<T> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
{
if (this.TryRead(out var item))
{
return UniTask.FromResult(item);
}
return ReadAsyncCore(cancellationToken);
}
async UniTask<T> ReadAsyncCore(CancellationToken cancellationToken = default(CancellationToken))
{
if (await WaitToReadAsync(cancellationToken))
{
if (TryRead(out var item))
{
return item;
}
}
throw new ChannelClosedException();
}
public abstract IUniTaskAsyncEnumerable<T> ReadAllAsync(CancellationToken cancellationToken = default(CancellationToken));
}
public abstract class ChannelWriter<T>
{
public abstract bool TryWrite(T item);
public abstract bool TryComplete(Exception error = null);
public void Complete(Exception error = null)
{
if (!TryComplete(error))
{
throw new ChannelClosedException();
}
}
}
public partial class ChannelClosedException : InvalidOperationException
{
public ChannelClosedException() :
base("Channel is already closed.")
{ }
public ChannelClosedException(string message) : base(message) { }
public ChannelClosedException(Exception innerException) :
base("Channel is already closed", innerException)
{ }
public ChannelClosedException(string message, Exception innerException) : base(message, innerException) { }
}
internal class SingleConsumerUnboundedChannel<T> : Channel<T>
{
readonly Queue<T> items;
readonly SingleConsumerUnboundedChannelReader readerSource;
UniTaskCompletionSource completedTaskSource;
UniTask completedTask;
Exception completionError;
bool closed;
public SingleConsumerUnboundedChannel()
{
items = new Queue<T>();
Writer = new SingleConsumerUnboundedChannelWriter(this);
readerSource = new SingleConsumerUnboundedChannelReader(this);
Reader = readerSource;
}
sealed class SingleConsumerUnboundedChannelWriter : ChannelWriter<T>
{
readonly SingleConsumerUnboundedChannel<T> parent;
public SingleConsumerUnboundedChannelWriter(SingleConsumerUnboundedChannel<T> parent)
{
this.parent = parent;
}
public override bool TryWrite(T item)
{
bool waiting;
lock (parent.items)
{
if (parent.closed) return false;
parent.items.Enqueue(item);
waiting = parent.readerSource.isWaiting;
}
if (waiting)
{
parent.readerSource.SingalContinuation();
}
return true;
}
public override bool TryComplete(Exception error = null)
{
bool waiting;
lock (parent.items)
{
if (parent.closed) return false;
parent.closed = true;
waiting = parent.readerSource.isWaiting;
if (parent.items.Count == 0)
{
if (error == null)
{
if (parent.completedTaskSource != null)
{
parent.completedTaskSource.TrySetResult();
}
else
{
parent.completedTask = UniTask.CompletedTask;
}
}
else
{
if (parent.completedTaskSource != null)
{
parent.completedTaskSource.TrySetException(error);
}
else
{
parent.completedTask = UniTask.FromException(error);
}
}
if (waiting)
{
parent.readerSource.SingalCompleted(error);
}
}
parent.completionError = error;
}
return true;
}
}
sealed class SingleConsumerUnboundedChannelReader : ChannelReader<T>, IUniTaskSource<bool>
{
readonly Action<object> CancellationCallbackDelegate = CancellationCallback;
readonly SingleConsumerUnboundedChannel<T> parent;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
UniTaskCompletionSourceCore<bool> core;
internal bool isWaiting;
public SingleConsumerUnboundedChannelReader(SingleConsumerUnboundedChannel<T> parent)
{
this.parent = parent;
TaskTracker.TrackActiveTask(this, 4);
}
public override UniTask Completion
{
get
{
if (parent.completedTaskSource != null) return parent.completedTaskSource.Task;
if (parent.closed)
{
return parent.completedTask;
}
parent.completedTaskSource = new UniTaskCompletionSource();
return parent.completedTaskSource.Task;
}
}
public override bool TryRead(out T item)
{
lock (parent.items)
{
if (parent.items.Count != 0)
{
item = parent.items.Dequeue();
// complete when all value was consumed.
if (parent.closed && parent.items.Count == 0)
{
if (parent.completionError != null)
{
if (parent.completedTaskSource != null)
{
parent.completedTaskSource.TrySetException(parent.completionError);
}
else
{
parent.completedTask = UniTask.FromException(parent.completionError);
}
}
else
{
if (parent.completedTaskSource != null)
{
parent.completedTaskSource.TrySetResult();
}
else
{
parent.completedTask = UniTask.CompletedTask;
}
}
}
}
else
{
item = default;
return false;
}
}
return true;
}
public override UniTask<bool> WaitToReadAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return UniTask.FromCanceled<bool>(cancellationToken);
}
lock (parent.items)
{
if (parent.items.Count != 0)
{
return CompletedTasks.True;
}
if (parent.closed)
{
if (parent.completionError == null)
{
return CompletedTasks.False;
}
else
{
return UniTask.FromException<bool>(parent.completionError);
}
}
cancellationTokenRegistration.Dispose();
core.Reset();
isWaiting = true;
this.cancellationToken = cancellationToken;
if (this.cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = this.cancellationToken.RegisterWithoutCaptureExecutionContext(CancellationCallbackDelegate, this);
}
return new UniTask<bool>(this, core.Version);
}
}
public void SingalContinuation()
{
core.TrySetResult(true);
}
public void SingalCancellation(CancellationToken cancellationToken)
{
TaskTracker.RemoveTracking(this);
core.TrySetCanceled(cancellationToken);
}
public void SingalCompleted(Exception error)
{
if (error != null)
{
TaskTracker.RemoveTracking(this);
core.TrySetException(error);
}
else
{
TaskTracker.RemoveTracking(this);
core.TrySetResult(false);
}
}
public override IUniTaskAsyncEnumerable<T> ReadAllAsync(CancellationToken cancellationToken = default)
{
return new ReadAllAsyncEnumerable(this, cancellationToken);
}
bool IUniTaskSource<bool>.GetResult(short token)
{
return core.GetResult(token);
}
void IUniTaskSource.GetResult(short token)
{
core.GetResult(token);
}
UniTaskStatus IUniTaskSource.GetStatus(short token)
{
return core.GetStatus(token);
}
void IUniTaskSource.OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
UniTaskStatus IUniTaskSource.UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
static void CancellationCallback(object state)
{
var self = (SingleConsumerUnboundedChannelReader)state;
self.SingalCancellation(self.cancellationToken);
}
sealed class ReadAllAsyncEnumerable : IUniTaskAsyncEnumerable<T>, IUniTaskAsyncEnumerator<T>
{
readonly Action<object> CancellationCallback1Delegate = CancellationCallback1;
readonly Action<object> CancellationCallback2Delegate = CancellationCallback2;
readonly SingleConsumerUnboundedChannelReader parent;
CancellationToken cancellationToken1;
CancellationToken cancellationToken2;
CancellationTokenRegistration cancellationTokenRegistration1;
CancellationTokenRegistration cancellationTokenRegistration2;
T current;
bool cacheValue;
bool running;
public ReadAllAsyncEnumerable(SingleConsumerUnboundedChannelReader parent, CancellationToken cancellationToken)
{
this.parent = parent;
this.cancellationToken1 = cancellationToken;
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
if (running)
{
throw new InvalidOperationException("Enumerator is already running, does not allow call GetAsyncEnumerator twice.");
}
if (this.cancellationToken1 != cancellationToken)
{
this.cancellationToken2 = cancellationToken;
}
if (this.cancellationToken1.CanBeCanceled)
{
this.cancellationTokenRegistration1 = this.cancellationToken1.RegisterWithoutCaptureExecutionContext(CancellationCallback1Delegate, this);
}
if (this.cancellationToken2.CanBeCanceled)
{
this.cancellationTokenRegistration2 = this.cancellationToken2.RegisterWithoutCaptureExecutionContext(CancellationCallback2Delegate, this);
}
running = true;
return this;
}
public T Current
{
get
{
if (cacheValue)
{
return current;
}
parent.TryRead(out current);
return current;
}
}
public UniTask<bool> MoveNextAsync()
{
cacheValue = false;
return parent.WaitToReadAsync(CancellationToken.None); // ok to use None, registered in ctor.
}
public UniTask DisposeAsync()
{
cancellationTokenRegistration1.Dispose();
cancellationTokenRegistration2.Dispose();
return default;
}
static void CancellationCallback1(object state)
{
var self = (ReadAllAsyncEnumerable)state;
self.parent.SingalCancellation(self.cancellationToken1);
}
static void CancellationCallback2(object state)
{
var self = (ReadAllAsyncEnumerable)state;
self.parent.SingalCancellation(self.cancellationToken2);
}
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 5ceb3107bbdd1f14eb39091273798360
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,17 +0,0 @@

#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
#pragma warning disable CS0436
namespace System.Runtime.CompilerServices
{
internal sealed class AsyncMethodBuilderAttribute : Attribute
{
public Type BuilderType { get; }
public AsyncMethodBuilderAttribute(Type builderType)
{
BuilderType = builderType;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 02ce354d37b10454e8376062f7cbe57a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,269 +0,0 @@

#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
namespace Cysharp.Threading.Tasks.CompilerServices
{
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder
{
IStateMachineRunnerPromise runnerPromise;
Exception ex;
// 1. Static Create method.
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTaskMethodBuilder Create()
{
return default;
}
// 2. TaskLike Task property.
public UniTask Task
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (runnerPromise != null)
{
return runnerPromise.Task;
}
else if (ex != null)
{
return UniTask.FromException(ex);
}
else
{
return UniTask.CompletedTask;
}
}
}
// 3. SetException
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetException(Exception exception)
{
if (runnerPromise == null)
{
ex = exception;
}
else
{
runnerPromise.SetException(exception);
}
}
// 4. SetResult
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetResult()
{
if (runnerPromise != null)
{
runnerPromise.SetResult();
}
}
// 5. AwaitOnCompleted
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (runnerPromise == null)
{
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
}
awaiter.OnCompleted(runnerPromise.MoveNext);
}
// 6. AwaitUnsafeOnCompleted
[DebuggerHidden]
[SecuritySafeCritical]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (runnerPromise == null)
{
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
}
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
}
// 7. Start
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
}
// 8. SetStateMachine
[DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// don't use boxed stateMachine.
}
#if DEBUG || !UNITY_2018_3_OR_NEWER
// Important for IDE debugger.
object debuggingId;
private object ObjectIdForDebugger
{
get
{
if (debuggingId == null)
{
debuggingId = new object();
}
return debuggingId;
}
}
#endif
}
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder<T>
{
IStateMachineRunnerPromise<T> runnerPromise;
Exception ex;
T result;
// 1. Static Create method.
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTaskMethodBuilder<T> Create()
{
return default;
}
// 2. TaskLike Task property.
public UniTask<T> Task
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (runnerPromise != null)
{
return runnerPromise.Task;
}
else if (ex != null)
{
return UniTask.FromException<T>(ex);
}
else
{
return UniTask.FromResult(result);
}
}
}
// 3. SetException
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetException(Exception exception)
{
if (runnerPromise == null)
{
ex = exception;
}
else
{
runnerPromise.SetException(exception);
}
}
// 4. SetResult
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetResult(T result)
{
if (runnerPromise == null)
{
this.result = result;
}
else
{
runnerPromise.SetResult(result);
}
}
// 5. AwaitOnCompleted
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (runnerPromise == null)
{
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
}
awaiter.OnCompleted(runnerPromise.MoveNext);
}
// 6. AwaitUnsafeOnCompleted
[DebuggerHidden]
[SecuritySafeCritical]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (runnerPromise == null)
{
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
}
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
}
// 7. Start
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
}
// 8. SetStateMachine
[DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// don't use boxed stateMachine.
}
#if DEBUG || !UNITY_2018_3_OR_NEWER
// Important for IDE debugger.
object debuggingId;
private object ObjectIdForDebugger
{
get
{
if (debuggingId == null)
{
debuggingId = new object();
}
return debuggingId;
}
}
#endif
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 68d72a45afdec574ebc26e7de2c38330
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,137 +0,0 @@

#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
namespace Cysharp.Threading.Tasks.CompilerServices
{
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskVoidMethodBuilder
{
IStateMachineRunner runner;
// 1. Static Create method.
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTaskVoidMethodBuilder Create()
{
return default;
}
// 2. TaskLike Task property(void)
public UniTaskVoid Task
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return default;
}
}
// 3. SetException
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetException(Exception exception)
{
// runner is finished, return first.
if (runner != null)
{
#if ENABLE_IL2CPP
// workaround for IL2CPP bug.
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction);
#else
runner.Return();
#endif
runner = null;
}
UniTaskScheduler.PublishUnobservedTaskException(exception);
}
// 4. SetResult
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetResult()
{
// runner is finished, return.
if (runner != null)
{
#if ENABLE_IL2CPP
// workaround for IL2CPP bug.
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction);
#else
runner.Return();
#endif
runner = null;
}
}
// 5. AwaitOnCompleted
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (runner == null)
{
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
}
awaiter.OnCompleted(runner.MoveNext);
}
// 6. AwaitUnsafeOnCompleted
[DebuggerHidden]
[SecuritySafeCritical]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (runner == null)
{
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
}
awaiter.UnsafeOnCompleted(runner.MoveNext);
}
// 7. Start
[DebuggerHidden]
public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
}
// 8. SetStateMachine
[DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// don't use boxed stateMachine.
}
#if DEBUG || !UNITY_2018_3_OR_NEWER
// Important for IDE debugger.
object debuggingId;
private object ObjectIdForDebugger
{
get
{
if (debuggingId == null)
{
debuggingId = new object();
}
return debuggingId;
}
}
#endif
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e891aaac17b933a47a9d7fa3b8e1226f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,380 +0,0 @@
#pragma warning disable CS1591
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Linq;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Cysharp.Threading.Tasks.CompilerServices
{
// #ENABLE_IL2CPP in this file is to avoid bug of IL2CPP VM.
// Issue is tracked on https://issuetracker.unity3d.com/issues/il2cpp-incorrect-results-when-calling-a-method-from-outside-class-in-a-struct
// but currently it is labeled `Won't Fix`.
internal interface IStateMachineRunner
{
Action MoveNext { get; }
void Return();
#if ENABLE_IL2CPP
Action ReturnAction { get; }
#endif
}
internal interface IStateMachineRunnerPromise : IUniTaskSource
{
Action MoveNext { get; }
UniTask Task { get; }
void SetResult();
void SetException(Exception exception);
}
internal interface IStateMachineRunnerPromise<T> : IUniTaskSource<T>
{
Action MoveNext { get; }
UniTask<T> Task { get; }
void SetResult(T result);
void SetException(Exception exception);
}
internal static class StateMachineUtility
{
// Get AsyncStateMachine internal state to check IL2CPP bug
public static int GetState(IAsyncStateMachine stateMachine)
{
var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.First(x => x.Name.EndsWith("__state"));
return (int)info.GetValue(stateMachine);
}
}
internal sealed class AsyncUniTaskVoid<TStateMachine> : IStateMachineRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
where TStateMachine : IAsyncStateMachine
{
static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
#if ENABLE_IL2CPP
public Action ReturnAction { get; }
#endif
TStateMachine stateMachine;
public Action MoveNext { get; }
public AsyncUniTaskVoid()
{
MoveNext = Run;
#if ENABLE_IL2CPP
ReturnAction = Return;
#endif
}
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
{
if (!pool.TryPop(out var result))
{
result = new AsyncUniTaskVoid<TStateMachine>();
}
TaskTracker.TrackActiveTask(result, 3);
runnerFieldRef = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
}
static AsyncUniTaskVoid()
{
TaskPool.RegisterSizeGetter(typeof(AsyncUniTaskVoid<TStateMachine>), () => pool.Size);
}
AsyncUniTaskVoid<TStateMachine> nextNode;
public ref AsyncUniTaskVoid<TStateMachine> NextNode => ref nextNode;
public void Return()
{
TaskTracker.RemoveTracking(this);
stateMachine = default;
pool.TryPush(this);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void Run()
{
stateMachine.MoveNext();
}
// dummy interface implementation for TaskTracker.
UniTaskStatus IUniTaskSource.GetStatus(short token)
{
return UniTaskStatus.Pending;
}
UniTaskStatus IUniTaskSource.UnsafeGetStatus()
{
return UniTaskStatus.Pending;
}
void IUniTaskSource.OnCompleted(Action<object> continuation, object state, short token)
{
}
void IUniTaskSource.GetResult(short token)
{
}
}
internal sealed class AsyncUniTask<TStateMachine> : IStateMachineRunnerPromise, IUniTaskSource, ITaskPoolNode<AsyncUniTask<TStateMachine>>
where TStateMachine : IAsyncStateMachine
{
static TaskPool<AsyncUniTask<TStateMachine>> pool;
#if ENABLE_IL2CPP
readonly Action returnDelegate;
#endif
public Action MoveNext { get; }
TStateMachine stateMachine;
UniTaskCompletionSourceCore<AsyncUnit> core;
AsyncUniTask()
{
MoveNext = Run;
#if ENABLE_IL2CPP
returnDelegate = Return;
#endif
}
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
{
if (!pool.TryPop(out var result))
{
result = new AsyncUniTask<TStateMachine>();
}
TaskTracker.TrackActiveTask(result, 3);
runnerPromiseFieldRef = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
}
AsyncUniTask<TStateMachine> nextNode;
public ref AsyncUniTask<TStateMachine> NextNode => ref nextNode;
static AsyncUniTask()
{
TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine>), () => pool.Size);
}
void Return()
{
TaskTracker.RemoveTracking(this);
core.Reset();
stateMachine = default;
pool.TryPush(this);
}
bool TryReturn()
{
TaskTracker.RemoveTracking(this);
core.Reset();
stateMachine = default;
return pool.TryPush(this);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void Run()
{
stateMachine.MoveNext();
}
public UniTask Task
{
[DebuggerHidden]
get
{
return new UniTask(this, core.Version);
}
}
[DebuggerHidden]
public void SetResult()
{
core.TrySetResult(AsyncUnit.Default);
}
[DebuggerHidden]
public void SetException(Exception exception)
{
core.TrySetException(exception);
}
[DebuggerHidden]
public void GetResult(short token)
{
try
{
core.GetResult(token);
}
finally
{
#if ENABLE_IL2CPP
// workaround for IL2CPP bug.
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
#else
TryReturn();
#endif
}
}
[DebuggerHidden]
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
[DebuggerHidden]
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
[DebuggerHidden]
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
}
internal sealed class AsyncUniTask<TStateMachine, T> : IStateMachineRunnerPromise<T>, IUniTaskSource<T>, ITaskPoolNode<AsyncUniTask<TStateMachine, T>>
where TStateMachine : IAsyncStateMachine
{
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
#if ENABLE_IL2CPP
readonly Action returnDelegate;
#endif
public Action MoveNext { get; }
TStateMachine stateMachine;
UniTaskCompletionSourceCore<T> core;
AsyncUniTask()
{
MoveNext = Run;
#if ENABLE_IL2CPP
returnDelegate = Return;
#endif
}
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
{
if (!pool.TryPop(out var result))
{
result = new AsyncUniTask<TStateMachine, T>();
}
TaskTracker.TrackActiveTask(result, 3);
runnerPromiseFieldRef = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
}
AsyncUniTask<TStateMachine, T> nextNode;
public ref AsyncUniTask<TStateMachine, T> NextNode => ref nextNode;
static AsyncUniTask()
{
TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine, T>), () => pool.Size);
}
void Return()
{
TaskTracker.RemoveTracking(this);
core.Reset();
stateMachine = default;
pool.TryPush(this);
}
bool TryReturn()
{
TaskTracker.RemoveTracking(this);
core.Reset();
stateMachine = default;
return pool.TryPush(this);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void Run()
{
// UnityEngine.Debug.Log($"MoveNext State:" + StateMachineUtility.GetState(stateMachine));
stateMachine.MoveNext();
}
public UniTask<T> Task
{
[DebuggerHidden]
get
{
return new UniTask<T>(this, core.Version);
}
}
[DebuggerHidden]
public void SetResult(T result)
{
core.TrySetResult(result);
}
[DebuggerHidden]
public void SetException(Exception exception)
{
core.TrySetException(exception);
}
[DebuggerHidden]
public T GetResult(short token)
{
try
{
return core.GetResult(token);
}
finally
{
#if ENABLE_IL2CPP
// workaround for IL2CPP bug.
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
#else
TryReturn();
#endif
}
}
[DebuggerHidden]
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
[DebuggerHidden]
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
[DebuggerHidden]
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
[DebuggerHidden]
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
}
}

Some files were not shown because too many files have changed in this diff Show More