diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/GooglePlayFileSystem.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/GooglePlayFileSystem.cs.meta
index af2a792f..d5b082ca 100644
--- a/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/GooglePlayFileSystem.cs.meta
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/GooglePlayFileSystem/GooglePlayFileSystem.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 2e26d6ba3f3c6cd48bc22d40f1857f89
+guid: 3a09145cd500f3f42b2a17524f0dd3f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem.meta
new file mode 100644
index 00000000..0d5147ba
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d6835d091fc4e4e438770512ec53c05c
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult.meta
new file mode 100644
index 00000000..f15f8f29
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ff9085fca05646b4e9f6dfec5f9cd5ab
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult/TPAssetBundleResult.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult/TPAssetBundleResult.cs
new file mode 100644
index 00000000..1febc13a
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult/TPAssetBundleResult.cs
@@ -0,0 +1,67 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using System.IO;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+using TapTapMiniGame;
+
+namespace YooAsset
+{
+ internal class TPAssetBundleResult : BundleResult
+ {
+ private readonly IFileSystem _fileSystem;
+ private readonly PackageBundle _packageBundle;
+ private readonly AssetBundle _assetBundle;
+
+ public TPAssetBundleResult(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.TapUnload(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
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult/TPAssetBundleResult.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult/TPAssetBundleResult.cs.meta
new file mode 100644
index 00000000..00b34d67
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult/TPAssetBundleResult.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e914b1b35e8a6ae48bdfe71a0614ab0a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation.meta
new file mode 100644
index 00000000..2ec085e5
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: dbbb8f216603c4042b3c29cdde607705
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadFileOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadFileOperation.cs
new file mode 100644
index 00000000..40bfaf60
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadFileOperation.cs
@@ -0,0 +1,111 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using UnityEngine;
+using YooAsset;
+
+internal class TPFSDownloadFileOperation : FSDownloadFileOperation
+{
+ protected enum ESteps
+ {
+ None,
+ CreateRequest,
+ CheckRequest,
+ TryAgain,
+ Done,
+ }
+
+ private readonly TaptapFileSystem _fileSystem;
+ private readonly DownloadFileOptions _options;
+ private UnityWebCacheRequestOperation _webCacheRequestOp;
+ private int _requestCount = 0;
+ private float _tryAgainTimer;
+ private int _failedTryAgain;
+ private ESteps _steps = ESteps.None;
+
+ internal TPFSDownloadFileOperation(TaptapFileSystem 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;
+ }
+ }
+ }
+
+ ///
+ /// 获取网络请求地址
+ ///
+ private string GetRequestURL()
+ {
+ // 轮流返回请求地址
+ _requestCount++;
+ if (_requestCount % 2 == 0)
+ return _options.FallbackURL;
+ else
+ return _options.MainURL;
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadFileOperation.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadFileOperation.cs.meta
new file mode 100644
index 00000000..b6380556
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadFileOperation.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e0d44d1a88d041a4cb6240d30d96fdf2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSInitializeOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSInitializeOperation.cs
new file mode 100644
index 00000000..83749f0f
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSInitializeOperation.cs
@@ -0,0 +1,20 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using YooAsset;
+
+internal partial class TPFSInitializeOperation : FSInitializeFileSystemOperation
+{
+ private readonly TaptapFileSystem _fileSystem;
+
+ public TPFSInitializeOperation(TaptapFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+ internal override void InternalStart()
+ {
+ Status = EOperationStatus.Succeed;
+ }
+ internal override void InternalUpdate()
+ {
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSInitializeOperation.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSInitializeOperation.cs.meta
new file mode 100644
index 00000000..2380d3b3
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSInitializeOperation.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 017c1f2fbc59ff8418cc781c5e66efef
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs
new file mode 100644
index 00000000..f7e9bc50
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs
@@ -0,0 +1,88 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using YooAsset;
+
+internal class TPFSLoadBundleOperation : FSLoadBundleOperation
+{
+ private enum ESteps
+ {
+ None,
+ LoadAssetBundle,
+ Done,
+ }
+
+ private readonly TaptapFileSystem _fileSystem;
+ private readonly PackageBundle _bundle;
+ private LoadWebAssetBundleOperation _loadWebAssetBundleOp;
+ private ESteps _steps = ESteps.None;
+
+ internal TPFSLoadBundleOperation(TaptapFileSystem 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 LoadTaptapAssetBundleOperation(_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 TPAssetBundleResult(_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
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs.meta
new file mode 100644
index 00000000..1180ae09
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 01680b24db924794b8adc1e0e6697865
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadPackageManifestOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadPackageManifestOperation.cs
new file mode 100644
index 00000000..c81c637c
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadPackageManifestOperation.cs
@@ -0,0 +1,95 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using YooAsset;
+
+internal class TPFSLoadPackageManifestOperation : FSLoadPackageManifestOperation
+{
+ private enum ESteps
+ {
+ None,
+ RequestPackageHash,
+ LoadPackageManifest,
+ Done,
+ }
+
+ private readonly TaptapFileSystem _fileSystem;
+ private readonly string _packageVersion;
+ private readonly int _timeout;
+ private RequestWebPackageHashOperation _requestPackageHashOp;
+ private LoadWebPackageManifestOperation _loadPackageManifestOp;
+ private ESteps _steps = ESteps.None;
+
+
+ public TPFSLoadPackageManifestOperation(TaptapFileSystem 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 RequestWebPackageHashOperation(_fileSystem.RemoteServices, _fileSystem.PackageName, _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;
+ string packageName = _fileSystem.PackageName;
+ var manifestServices = _fileSystem.ManifestServices;
+ var remoteServices = _fileSystem.RemoteServices;
+ _loadPackageManifestOp = new LoadWebPackageManifestOperation(manifestServices, remoteServices, packageName, _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
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadPackageManifestOperation.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadPackageManifestOperation.cs.meta
new file mode 100644
index 00000000..4d2ec97e
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadPackageManifestOperation.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a9900531297a5a140806316f844fa0a0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSRequestPackageVersionOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSRequestPackageVersionOperation.cs
new file mode 100644
index 00000000..87f7e6ae
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSRequestPackageVersionOperation.cs
@@ -0,0 +1,64 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using YooAsset;
+
+internal class TPFSRequestPackageVersionOperation : FSRequestPackageVersionOperation
+{
+ private enum ESteps
+ {
+ None,
+ RequestPackageVersion,
+ Done,
+ }
+
+ private readonly TaptapFileSystem _fileSystem;
+ private readonly bool _appendTimeTicks;
+ private readonly int _timeout;
+ private RequestWebPackageVersionOperation _requestWebPackageVersionOp;
+ private ESteps _steps = ESteps.None;
+
+
+ internal TPFSRequestPackageVersionOperation(TaptapFileSystem 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 RequestWebPackageVersionOperation(_fileSystem.RemoteServices, _fileSystem.PackageName, _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
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSRequestPackageVersionOperation.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSRequestPackageVersionOperation.cs.meta
new file mode 100644
index 00000000..0e84e87c
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSRequestPackageVersionOperation.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 877f877fd3586974d90c7c306efdf4d1
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal.meta
new file mode 100644
index 00000000..d16d5fa2
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e4ea0eed64f86c54c82153463d3773bf
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs
new file mode 100644
index 00000000..71a6fac8
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs
@@ -0,0 +1,114 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using UnityEngine;
+
+namespace YooAsset
+{
+ internal class LoadTaptapAssetBundleOperation : LoadWebAssetBundleOperation
+ {
+ protected enum ESteps
+ {
+ None,
+ CreateRequest,
+ CheckRequest,
+ TryAgain,
+ Done,
+ }
+
+ private readonly PackageBundle _bundle;
+ private readonly DownloadFileOptions _options;
+ private UnityTaptapAssetBundleRequestOperation _unityAssetBundleRequestOp;
+
+ private int _requestCount = 0;
+ private float _tryAgainTimer;
+ private int _failedTryAgain;
+ private ESteps _steps = ESteps.None;
+
+
+ internal LoadTaptapAssetBundleOperation(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 UnityTaptapAssetBundleRequestOperation(_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;
+ }
+ }
+ }
+
+ ///
+ /// 获取网络请求地址
+ ///
+ private string GetRequestURL()
+ {
+ // 轮流返回请求地址
+ _requestCount++;
+ if (_requestCount % 2 == 0)
+ return _options.FallbackURL;
+ else
+ return _options.MainURL;
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs.meta
new file mode 100644
index 00000000..854190ce
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fabbe424782f96a4490979f4f68c6322
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/UnityTaptapAssetBundleRequestOperation.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/UnityTaptapAssetBundleRequestOperation.cs
new file mode 100644
index 00000000..f688929c
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/UnityTaptapAssetBundleRequestOperation.cs
@@ -0,0 +1,95 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using UnityEngine.Networking;
+using UnityEngine;
+using TapTapMiniGame;
+
+namespace YooAsset
+{
+ internal class UnityTaptapAssetBundleRequestOperation : UnityWebRequestOperation
+ {
+ protected enum ESteps
+ {
+ None,
+ CreateRequest,
+ Download,
+ Done,
+ }
+
+ private readonly PackageBundle _packageBundle;
+ private UnityWebRequestAsyncOperation _requestOperation;
+ private ESteps _steps = ESteps.None;
+
+ ///
+ /// 请求结果
+ ///
+ public AssetBundle Result { private set; get; }
+
+ internal UnityTaptapAssetBundleRequestOperation(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 = (DownloadHandlerTapAssetBundle)_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 = TapAssetBundle.GetAssetBundle(_requestURL);
+ _webRequest.disposeDownloadHandlerOnDispose = true;
+ _requestOperation = _webRequest.SendWebRequest();
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/UnityTaptapAssetBundleRequestOperation.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/UnityTaptapAssetBundleRequestOperation.cs.meta
new file mode 100644
index 00000000..01a2774f
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/UnityTaptapAssetBundleRequestOperation.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ce0d7ec006993ef41b16f32335dc6224
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs
new file mode 100644
index 00000000..2c942e21
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs
@@ -0,0 +1,271 @@
+#if UNITY_WEBGL && TAPMINIGAME
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using UnityEngine;
+using YooAsset;
+using TapTapMiniGame;
+
+public static class TaptapFileSystemCreater
+{
+ public static FileSystemParameters CreateFileSystemParameters(string packageRoot)
+ {
+ string fileSystemClass = $"{nameof(TaptapFileSystem)},YooAsset.MiniGame";
+ var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
+ return fileSystemParams;
+ }
+}
+
+///
+/// TapTap小游戏
+/// 参考:https://developer.taptap.cn/minigameapidoc/dev/engine/unity-adaptation/guide/
+///
+internal class TaptapFileSystem : IFileSystem
+{
+ private class WebRemoteServices : IRemoteServices
+ {
+ private readonly string _webPackageRoot;
+ protected readonly Dictionary _mapping = new Dictionary(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 _cacheFilePathMapping = new Dictionary(10000);
+ private TapFileSystemManager _fileSystemMgr;
+ private string _tapCacheRoot = string.Empty;
+
+ ///
+ /// 包裹名称
+ ///
+ public string PackageName { private set; get; }
+
+ ///
+ /// 文件根目录
+ ///
+ public string FileRoot
+ {
+ get
+ {
+ return _tapCacheRoot;
+ }
+ }
+
+ ///
+ /// 文件数量
+ ///
+ public int FileCount
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ #region 自定义参数
+ ///
+ /// 自定义参数:远程服务接口
+ ///
+ public IRemoteServices RemoteServices { private set; get; } = null;
+
+ ///
+ /// 自定义参数:解密方法类
+ ///
+ public IWebDecryptionServices DecryptionServices { private set; get; }
+
+ ///
+ /// 自定义参数:资源清单服务类
+ ///
+ public IManifestRestoreServices ManifestServices { private set; get; }
+ #endregion
+
+
+ public TaptapFileSystem()
+ {
+ }
+ public virtual FSInitializeFileSystemOperation InitializeFileSystemAsync()
+ {
+ var operation = new TPFSInitializeOperation(this);
+ return operation;
+ }
+ public virtual FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout)
+ {
+ var operation = new TPFSLoadPackageManifestOperation(this, packageVersion, timeout);
+ return operation;
+ }
+ public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout)
+ {
+ var operation = new TPFSRequestPackageVersionOperation(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 TPFSDownloadFileOperation(this, bundle, options);
+ return operation;
+ }
+ public virtual FSLoadBundleOperation LoadBundleFile(PackageBundle bundle)
+ {
+ if (bundle.BundleType == (int)EBuildBundleType.AssetBundle)
+ {
+ var operation = new TPFSLoadBundleOperation(this, bundle);
+ return operation;
+ }
+ else
+ {
+ string error = $"{nameof(TaptapFileSystem)} 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;
+ _tapCacheRoot = rootDirectory;
+
+ if (string.IsNullOrEmpty(_tapCacheRoot))
+ {
+ throw new System.Exception("请配置小游戏的缓存根目录!");
+ }
+
+ // 注意:CDN服务未启用的情况下,使用WEB服务器
+ if (RemoteServices == null)
+ {
+ string webRoot = PathUtility.Combine(Application.streamingAssetsPath, YooAssetSettingsData.Setting.DefaultYooFolderName, packageName);
+ RemoteServices = new WebRemoteServices(webRoot);
+ }
+
+ _fileSystemMgr = Tap.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();
+ }
+ }
+ public virtual string ReadBundleFileText(PackageBundle bundle)
+ {
+ if (CheckCacheFileExist(bundle))
+ {
+ string filePath = GetCacheFileLoadPath(bundle);
+ return _fileSystemMgr.ReadFileSync(filePath, "utf8");
+ }
+ else
+ {
+ return string.Empty;
+ }
+ }
+
+ #region 内部方法
+ public TapFileSystemManager 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(_tapCacheRoot, bundle.FileName);
+ _cacheFilePathMapping.Add(bundle.BundleGUID, filePath);
+ }
+ return filePath;
+ }
+ #endregion
+}
+#endif
\ No newline at end of file
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs.meta
new file mode 100644
index 00000000..af2a792f
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2e26d6ba3f3c6cd48bc22d40f1857f89
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/YooAsset.MiniGame.asmdef b/Assets/YooAsset/Samples~/Mini Game/Runtime/YooAsset.MiniGame.asmdef
index 34ad5480..020bfc21 100644
--- a/Assets/YooAsset/Samples~/Mini Game/Runtime/YooAsset.MiniGame.asmdef
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/YooAsset.MiniGame.asmdef
@@ -6,7 +6,8 @@
"GUID:5efd170ecd8084500bed5692932fe14e",
"GUID:bb21d6197862c4c3e863390dec9859a7",
"GUID:870f26a2ffa82429195df0861505c5d5",
- "GUID:870f26a2ffa82429195df0861505c5d5"
+ "GUID:870f26a2ffa82429195df0861505c5d5",
+ "GUID:6921e41464907054da1a045ea64ca16f"
],
"includePlatforms": [],
"excludePlatforms": [],