From 21701562165c25fb34b2e08ada25cb113e5fffaa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BD=95=E5=86=A0=E5=B3=B0?= <33317070@qq.com>
Date: Thu, 21 May 2026 16:56:06 +0800
Subject: [PATCH] feat : oppo file system support
---
.../Mini Game/Runtime/OppoFileSystem.meta | 8 ++
.../Runtime/OppoFileSystem/OppoFileSystem.cs | 34 +++++++++
.../OppoFileSystem/OppoFileSystem.cs.meta | 11 +++
.../Runtime/OppoFileSystem/OppoPlatform.cs | 30 ++++++++
.../OppoFileSystem/OppoPlatform.cs.meta | 11 +++
.../Runtime/OppoFileSystem/README.md | 74 +++++++++++++++++++
.../Runtime/OppoFileSystem/README.md.meta | 7 ++
7 files changed, 175 insertions(+)
create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem.meta
create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoFileSystem.cs
create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoFileSystem.cs.meta
create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoPlatform.cs
create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoPlatform.cs.meta
create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/README.md
create mode 100644 Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/README.md.meta
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem.meta
new file mode 100644
index 00000000..4e34d3fa
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d3406054572d78a42afc498103c31643
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoFileSystem.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoFileSystem.cs
new file mode 100644
index 00000000..ca790b2b
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoFileSystem.cs
@@ -0,0 +1,34 @@
+#if UNITY_WEBGL && OPPOMINIGAME
+using YooAsset;
+
+public static class OppoFileSystemCreater
+{
+ public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteService remoteService)
+ {
+ string fileSystemClass = $"{nameof(OppoFileSystem)},YooAsset.MiniGame";
+ var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
+ fileSystemParams.AddParameter(EFileSystemParameter.RemoteService, remoteService);
+ return fileSystemParams;
+ }
+ public static FileSystemParameters CreateFileSystemParameters(string packageRoot, IRemoteService remoteService, IBundleDecryptor decryptor)
+ {
+ string fileSystemClass = $"{nameof(OppoFileSystem)},YooAsset.MiniGame";
+ var fileSystemParams = new FileSystemParameters(fileSystemClass, packageRoot);
+ fileSystemParams.AddParameter(EFileSystemParameter.RemoteService, remoteService);
+ fileSystemParams.AddParameter(EFileSystemParameter.AssetbundleDecryptor, decryptor);
+ return fileSystemParams;
+ }
+}
+
+///
+/// OPPO 小游戏文件系统
+///
+internal class OppoFileSystem : WebGameFileSystem
+{
+ ///
+ protected override IWebGamePlatform CreatePlatform(string packageRoot)
+ {
+ return new OppoPlatform();
+ }
+}
+#endif
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoFileSystem.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoFileSystem.cs.meta
new file mode 100644
index 00000000..e1c64066
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoFileSystem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e25c7db2877c44ed9f9105dbd0057c47
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoPlatform.cs b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoPlatform.cs
new file mode 100644
index 00000000..bd8aa2bc
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoPlatform.cs
@@ -0,0 +1,30 @@
+#if UNITY_WEBGL && OPPOMINIGAME
+using UnityEngine;
+using UnityEngine.Networking;
+using YooAsset;
+
+///
+/// OPPO 小游戏平台实现
+///
+internal class OppoPlatform : IWebGamePlatform
+{
+ ///
+ public UnityWebRequest CreateAssetBundleRequest(string url)
+ {
+ return UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(url);
+ }
+
+ ///
+ public AssetBundle ExtractAssetBundle(UnityWebRequest request)
+ {
+ var downloadHandler = (DownloadHandlerAssetBundle)request.downloadHandler;
+ return downloadHandler.assetBundle;
+ }
+
+ ///
+ public void UnloadAssetBundle(AssetBundle assetBundle, bool unloadAll)
+ {
+ assetBundle.Unload(unloadAll);
+ }
+}
+#endif
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoPlatform.cs.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoPlatform.cs.meta
new file mode 100644
index 00000000..0b8baa58
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/OppoPlatform.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c88ea27c91d34f5a9bb45bd9f6b025a3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/README.md b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/README.md
new file mode 100644
index 00000000..9ea3d5d8
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/README.md
@@ -0,0 +1,74 @@
+# OPPO 小游戏文件系统
+
+该示例用于在 YooAsset 的 WebGL 运行模式下接入 OPPO 小游戏。
+
+参考文档:[OPPO 小游戏资源缓存](https://github.com/oppominigame/unity-webgl-to-oppo-minigame/blob/main/doc/AssetCache.md)
+
+## 环境要求
+
+先安装 OPPO Unity WebGL 小游戏 SDK,并将项目切换到 WebGL 构建目标。
+
+在 WebGL Player 的 Scripting Define Symbols 中启用以下宏:
+
+- `OPPOMINIGAME`
+
+该宏是 YooAsset OPPO 小游戏示例约定的编译开关,用于和其它小游戏平台适配代码保持一致。
+
+## 初始化 YooAsset
+
+在 OPPO 小游戏构建中初始化 `WebPlayModeOptions` 时,使用 `OppoFileSystemCreater` 创建文件系统参数。
+
+```csharp
+#if UNITY_WEBGL && OPPOMINIGAME && !UNITY_EDITOR
+var createParameters = new WebPlayModeOptions();
+
+string defaultHostServer = GetHostServerURL();
+string fallbackHostServer = GetHostServerURL();
+string packageRoot = "/__GAME_FILE_CACHE";
+IRemoteService remoteService = new RemoteService(defaultHostServer, fallbackHostServer);
+
+createParameters.WebServerFileSystemParameters =
+ OppoFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteService);
+
+var initializationOperation = package.InitializePackageAsync(createParameters);
+#endif
+```
+
+对当前文件系统来说,`packageRoot` 只需要是一个非空值。OPPO 真正的 AssetBundle 缓存行为由生成后小游戏工程里的 `manifest.json` 控制。
+
+## OPPO 缓存配置
+
+配置小游戏工程的 `manifest.json`,让 OPPO 能识别 YooAsset 的资源包 URL:
+
+```json
+{
+ "disableBundleCache": false,
+ "gameCDNRoot": "https://your-cdn.example.com/StreamingAssets",
+ "bundlePathIdentifier": "StreamingAssets;bundles",
+ "excludeFileExtensions": ".json;.hash;.version;.bytes",
+ "bundleHashLength": 32,
+ "defaultReleaseSize": 30,
+ "keepOldVersion": false,
+ "enableCacheLog": true
+}
+```
+
+`gameCDNRoot` 必须和 YooAsset `IRemoteService` 返回的 CDN 根地址一致。如果不匹配,OPPO 会把请求当成普通网络请求处理,不会进入资源缓存逻辑。
+
+`excludeFileExtensions` 建议包含 YooAsset 的清单、版本和哈希文件后缀,让 OPPO 只缓存 AssetBundle 文件。
+
+## 资源包命名
+
+OPPO 通过远端文件名里的 hash 识别可缓存资源。YooAsset 推荐只使用 `HashName` 文件命名风格。
+
+`HashName` 会生成纯 hash 文件名,例如:
+
+```text
+8d265a9dfd6cb7669cdb8b726f0afb1e.bundle
+```
+
+该命名方式和 OPPO 资源缓存规则最匹配,也能避免暴露原始 Bundle 名称。OPPO 缓存构建不建议使用 `BundleName` 或 `BundleName_HashName`。
+
+## 注意事项
+
+加密 AssetBundle 仍然会走 YooAsset 常规的 Web 下载和解密流程。非加密 AssetBundle 会使用 OPPO 平台适配器;当 `manifest.json` 缓存规则匹配时,可由 OPPO 小游戏运行时缓存。
diff --git a/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/README.md.meta b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/README.md.meta
new file mode 100644
index 00000000..2dfbcecb
--- /dev/null
+++ b/Assets/YooAsset/Samples~/Mini Game/Runtime/OppoFileSystem/README.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: a0f637cda89f4889a7f7d7c169b4390b
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant: