From 82d7bc8fefcf9dd090ee35d0fdbdf87e3c93bd24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=86=A0=E5=B3=B0?= Date: Sat, 30 Aug 2025 18:09:28 +0800 Subject: [PATCH] =?UTF-8?q?fix=20#614=20=E5=A2=9E=E5=8A=A0Taptap=E5=B0=8F?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E6=89=A9=E5=B1=95=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GooglePlayFileSystem.cs.meta | 2 +- .../Mini Game/Runtime/TaptapFileSystem.meta | 8 + .../TaptapFileSystem/BundleResult.meta | 8 + .../BundleResult/TPAssetBundleResult.cs | 67 +++++ .../BundleResult/TPAssetBundleResult.cs.meta | 11 + .../Runtime/TaptapFileSystem/Operation.meta | 8 + .../Operation/TPFSDownloadFileOperation.cs | 111 +++++++ .../TPFSDownloadFileOperation.cs.meta | 11 + .../Operation/TPFSInitializeOperation.cs | 20 ++ .../Operation/TPFSInitializeOperation.cs.meta | 11 + .../Operation/TPFSLoadBundleOperation.cs | 88 ++++++ .../Operation/TPFSLoadBundleOperation.cs.meta | 11 + .../TPFSLoadPackageManifestOperation.cs | 95 ++++++ .../TPFSLoadPackageManifestOperation.cs.meta | 11 + .../TPFSRequestPackageVersionOperation.cs | 64 +++++ ...TPFSRequestPackageVersionOperation.cs.meta | 11 + .../TaptapFileSystem/Operation/internal.meta | 8 + .../LoadTaptapAssetBundleOperation.cs | 114 ++++++++ .../LoadTaptapAssetBundleOperation.cs.meta | 11 + .../UnityTaptapAssetBundleRequestOperation.cs | 95 ++++++ ...yTaptapAssetBundleRequestOperation.cs.meta | 11 + .../TaptapFileSystem/TaptapFileSystem.cs | 271 ++++++++++++++++++ .../TaptapFileSystem/TaptapFileSystem.cs.meta | 11 + .../Runtime/YooAsset.MiniGame.asmdef | 3 +- 24 files changed, 1059 insertions(+), 2 deletions(-) create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult/TPAssetBundleResult.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/BundleResult/TPAssetBundleResult.cs.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadFileOperation.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSDownloadFileOperation.cs.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSInitializeOperation.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSInitializeOperation.cs.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadBundleOperation.cs.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadPackageManifestOperation.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSLoadPackageManifestOperation.cs.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSRequestPackageVersionOperation.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/TPFSRequestPackageVersionOperation.cs.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/LoadTaptapAssetBundleOperation.cs.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/UnityTaptapAssetBundleRequestOperation.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/Operation/internal/UnityTaptapAssetBundleRequestOperation.cs.meta create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/TaptapFileSystem/TaptapFileSystem.cs.meta 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": [],