DefaultWebServerFileSystem Web服务器文件系统
模块概述
DefaultWebServerFileSystem 是 YooAsset 的 Web 服务器文件系统,专为 WebGL 平台的同域资源加载而设计。该文件系统从与 WebGL 构建相同的服务器(StreamingAssets 目录)加载资源,通过 Catalog 目录文件管理内置资源清单。
核心特性
- 同域加载:从 WebGL 构建所在服务器加载资源
- Catalog 管理:通过目录文件追踪可用资源
- 路径映射:自动将本地路径转换为 WWW 路径
- Unity 缓存控制:可选择禁用 Unity 的 Web 请求缓存
- 加密支持:支持
IWebDecryptionServices解密 Web 资源
设计目标
| 目标 | 说明 |
|---|---|
| WebGL 内置资源 | 加载与 WebGL 构建一起部署的资源 |
| 资源追踪 | 通过 Catalog 文件精确知道哪些资源可用 |
| 无跨域问题 | 从同一服务器加载,避免 CORS 问题 |
| 与 Buildin 对应 | WebGL 版本的 DefaultBuildinFileSystem |
文件结构
DefaultWebServerFileSystem/
├── DefaultWebServerFileSystem.cs # 文件系统主类
└── Operation/ # 操作类
├── DWSFSInitializeOperation.cs # 初始化操作
├── DWSFSRequestPackageVersionOperation.cs # 请求版本操作
├── DWSFSLoadPackageManifestOperation.cs # 加载清单操作
├── DWSFSLoadBundleOperation.cs # 加载资源包操作
└── internal/ # 内部操作类
├── LoadWebServerCatalogFileOperation.cs # 加载目录文件
├── RequestWebServerPackageVersionOperation.cs # 请求版本文件
├── RequestWebServerPackageHashOperation.cs # 请求哈希文件
└── LoadWebServerPackageManifestOperation.cs # 加载清单文件
依赖的共享模块
DefaultWebServerFileSystem 依赖 WebGame 目录下的共享操作类:
FileSystem/WebGame/Operation/
├── LoadWebAssetBundleOperation.cs # Web 资源包加载基类
├── LoadWebNormalAssetBundleOperation.cs # 普通资源包加载
└── LoadWebEncryptAssetBundleOperation.cs # 加密资源包加载
核心类说明
DefaultWebServerFileSystem
Web 服务器文件系统的主类,实现 IFileSystem 接口。
内部类
public class FileWrapper
{
public string FileName { private set; get; }
public FileWrapper(string fileName)
{
FileName = fileName;
}
}
基本属性
| 属性 | 类型 | 说明 |
|---|---|---|
PackageName |
string |
包裹名称 |
FileRoot |
string |
Web 包裹根目录 |
FileCount |
int |
始终返回 0 |
DownloadBackend |
IDownloadBackend |
下载后台接口 |
自定义参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
DisableUnityWebCache |
bool |
false |
禁用 Unity 的网络缓存 |
DecryptionServices |
IWebDecryptionServices |
null |
Web 解密服务接口 |
ManifestServices |
IManifestRestoreServices |
null |
清单服务接口 |
核心方法
// 生命周期
void OnCreate(string packageName, string packageRoot);
void OnDestroy();
void SetParameter(string name, object value);
// 异步操作
FSInitializeFileSystemOperation InitializeFileSystemAsync();
FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout);
FSLoadPackageManifestOperation LoadPackageManifestAsync(string packageVersion, int timeout);
FSLoadBundleOperation LoadBundleFile(PackageBundle bundle);
FSClearCacheFilesOperation ClearCacheFilesAsync(...); // 直接返回完成
// 不支持的操作
FSDownloadFileOperation DownloadFileAsync(...); // 抛出 NotImplementedException
string GetBundleFilePath(...); // 抛出 NotImplementedException
byte[] ReadBundleFileData(...); // 抛出 NotImplementedException
string ReadBundleFileText(...); // 抛出 NotImplementedException
// 文件查询(基于 Catalog)
bool Belong(PackageBundle bundle); // 检查是否在 _wrappers 字典中
bool Exists(PackageBundle bundle); // 检查是否在 _wrappers 字典中
bool NeedDownload(PackageBundle bundle);// 始终返回 false
bool NeedUnpack(PackageBundle bundle); // 始终返回 false
bool NeedImport(PackageBundle bundle); // 始终返回 false
内部方法
// 路径获取
string GetDefaultWebPackageRoot(string packageName); // 默认包裹根目录
string GetWebFileLoadPath(PackageBundle bundle); // 资源文件加载路径
string GetWebPackageVersionFilePath(); // 版本文件路径
string GetWebPackageHashFilePath(string packageVersion); // 哈希文件路径
string GetWebPackageManifestFilePath(string packageVersion); // 清单文件路径
string GetCatalogBinaryFileLoadPath(); // Catalog 文件路径
// Catalog 管理
bool RecordCatalogFile(string bundleGUID, FileWrapper wrapper);
Catalog 目录系统
DefaultWebServerFileSystem 使用 Catalog 文件追踪可用的内置资源,这与 DefaultBuildinFileSystem 的机制相同。
Catalog 文件
| 文件 | 路径 | 说明 |
|---|---|---|
| Catalog 二进制文件 | {PackageRoot}/{PackageName}_buildin.bytes |
资源目录信息 |
Catalog 数据结构
// _wrappers 字典:BundleGUID → FileWrapper
protected readonly Dictionary<string, FileWrapper> _wrappers;
// FileWrapper 包含文件名信息
public class FileWrapper
{
public string FileName { private set; get; }
}
Belong 与 Exists 判断
public virtual bool Belong(PackageBundle bundle)
{
// 检查 Catalog 中是否包含该资源
return _wrappers.ContainsKey(bundle.BundleGUID);
}
public virtual bool Exists(PackageBundle bundle)
{
// 同样基于 Catalog 判断
return _wrappers.ContainsKey(bundle.BundleGUID);
}
操作类说明
DWSFSInitializeOperation
初始化操作,加载 Catalog 目录文件。
状态流程:
LoadCatalogFile
└── LoadWebServerCatalogFileOperation
└── 请求 {PackageName}_buildin.bytes
├── 下载二进制数据
└── 反序列化 Catalog
├── 验证 PackageName
└── 遍历 Wrappers
└── RecordCatalogFile()
├── 成功 → Succeed
└── 失败 → Failed
LoadWebServerCatalogFileOperation
加载 Web 服务器 Catalog 文件的内部操作。
// 关键流程
if (_steps == ESteps.LoadCatalog)
{
var catalog = CatalogTools.DeserializeFromBinary(_webDataRequestOp.Result);
// 验证包裹名称
if (catalog.PackageName != _fileSystem.PackageName)
{
Error = $"Catalog file package name {catalog.PackageName} cannot match...";
return;
}
// 记录所有内置资源
foreach (var wrapper in catalog.Wrappers)
{
var fileWrapper = new DefaultWebServerFileSystem.FileWrapper(wrapper.FileName);
_fileSystem.RecordCatalogFile(wrapper.BundleGUID, fileWrapper);
}
}
DWSFSRequestPackageVersionOperation
请求包裹版本操作,从 Web 服务器获取版本文件。
状态流程:
RequestPackageVersion
└── RequestWebServerPackageVersionOperation
└── 请求 {FileRoot}/{PackageName}_Version.txt
├── 转换为 WWW 路径
└── 下载文本内容
├── 成功 → PackageVersion
└── 失败 → Failed
DWSFSLoadPackageManifestOperation
加载资源清单操作,从 Web 服务器加载并解析清单。
状态流程:
RequestWebPackageHash
└── RequestWebServerPackageHashOperation
└── 请求 {PackageName}_{Version}.hash
├── 成功 → PackageHash
└── 失败 → Failed
↓
LoadWebPackageManifest
└── LoadWebServerPackageManifestOperation
├── 请求 {PackageName}_{Version}.bytes
├── 验证哈希
└── 反序列化清单
├── 成功 → Manifest
└── 失败 → Failed
LoadWebServerPackageManifestOperation
加载清单文件的内部操作,包含哈希验证。
状态流程:
RequestFileData
└── DownloadBytesRequest
└── 下载清单二进制数据
↓
VerifyFileData
└── ManifestTools.VerifyManifestData()
├── 验证成功 → LoadManifest
└── 验证失败 → Failed
↓
LoadManifest
└── DeserializeManifestOperation
├── 反序列化成功 → Manifest → Succeed
└── 反序列化失败 → Failed
DWSFSLoadAssetBundleOperation
加载资源包操作,从 Web 服务器加载 AssetBundle。
状态流程:
LoadWebAssetBundle
├── 获取文件路径 → 转换为 WWW 路径
│
├── 未加密 → LoadWebNormalAssetBundleOperation
│ └── UnityWebRequestAssetBundle
│ ├── 成功 → AssetBundleResult
│ └── 失败 → Failed
│
└── 已加密 → LoadWebEncryptAssetBundleOperation
└── DownloadBytesRequest
└── IWebDecryptionServices.LoadAssetBundle()
├── 成功 → AssetBundleResult
└── 失败 → Failed
路径转换
// 获取本地文件路径
string fileLoadPath = _fileSystem.GetWebFileLoadPath(_bundle);
// 转换为 WWW 请求路径
string mainURL = DownloadSystemHelper.ConvertToWWWPath(fileLoadPath);
// 主 URL 和备用 URL 相同(同域加载)
DownloadFileOptions options = new DownloadFileOptions(int.MaxValue);
options.SetURL(mainURL, mainURL);
同步加载限制
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);
}
}
路径映射机制
DefaultWebServerFileSystem 使用路径缓存优化性能:
// 文件路径缓存
protected readonly Dictionary<string, string> _webFilePathMapping = new Dictionary<string, string>(10000);
public string GetWebFileLoadPath(PackageBundle bundle)
{
if (_webFilePathMapping.TryGetValue(bundle.BundleGUID, out string filePath) == false)
{
// 组合路径:{WebPackageRoot}/{FileName}
filePath = PathUtility.Combine(_webPackageRoot, bundle.FileName);
_webFilePathMapping.Add(bundle.BundleGUID, filePath);
}
return filePath;
}
默认路径
protected string GetDefaultWebPackageRoot(string packageName)
{
// 使用默认的内置资源根目录(StreamingAssets)
string rootDirectory = YooAssetSettingsData.GetYooDefaultBuildinRoot();
return PathUtility.Combine(rootDirectory, packageName);
}
与 DefaultWebRemoteFileSystem 对比
| 特性 | DefaultWebServerFileSystem | DefaultWebRemoteFileSystem |
|---|---|---|
| 用途 | WebGL 同域内置资源 | WebGL 跨域远程资源 |
| Catalog 系统 | ✅ 有 | ❌ 无 |
| Belong/Exists | 基于 Catalog 判断 | 始终返回 true |
| 远程服务 | ❌ 不需要 | ✅ 需要 IRemoteServices |
| URL 生成 | 本地路径转 WWW | 远程服务接口生成 |
| 主/备用地址 | 相同(同域) | 不同(可配置) |
使用示例
基础配置
// 创建 Web 服务器文件系统参数
var webServerParams = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
// 初始化包裹(WebGL 模式)
var initParams = new WebPlayModeParameters();
initParams.WebServerFileSystemParameters = webServerParams;
initParams.WebRemoteFileSystemParameters = webRemoteParams; // 可选:跨域资源
var initOp = package.InitializeAsync(initParams);
自定义包裹根目录
// 创建参数时指定自定义路径
var webServerParams = FileSystemParameters.CreateDefaultWebServerFileSystemParameters(
packageRoot: "Assets/StreamingAssets/MyCustomPath/DefaultPackage"
);
禁用 Unity Web 缓存
var webServerParams = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
// 禁用 Unity 的 Web 请求缓存
webServerParams.AddParameter(FileSystemParametersDefine.DISABLE_UNITY_WEB_CACHE, true);
配置 Web 解密服务
// 自定义 Web 解密服务
class GameWebDecryptionServices : IWebDecryptionServices
{
public WebDecryptResult LoadAssetBundle(WebDecryptFileInfo fileInfo)
{
byte[] decryptedData = Decrypt(fileInfo.FileData);
AssetBundle bundle = AssetBundle.LoadFromMemory(decryptedData);
return new WebDecryptResult { Result = bundle };
}
}
var webServerParams = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
// 设置 Web 解密服务
webServerParams.AddParameter(
FileSystemParametersDefine.DECRYPTION_SERVICES,
new GameWebDecryptionServices()
);
WebGL 双文件系统配置
// WebGL 典型配置:内置 + 远程
var webServerParams = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
var webRemoteParams = FileSystemParameters.CreateDefaultWebRemoteFileSystemParameters(
remoteServices: new GameRemoteServices()
);
var initParams = new WebPlayModeParameters();
initParams.WebServerFileSystemParameters = webServerParams; // 同域内置资源
initParams.WebRemoteFileSystemParameters = webRemoteParams; // 跨域热更资源
var initOp = package.InitializeAsync(initParams);
参数常量
// Unity 缓存控制
FileSystemParametersDefine.DISABLE_UNITY_WEB_CACHE // bool: 禁用 Unity Web 缓存
// 服务接口
FileSystemParametersDefine.DECRYPTION_SERVICES // IWebDecryptionServices: Web 解密服务
FileSystemParametersDefine.MANIFEST_SERVICES // IManifestRestoreServices: 清单服务
类继承关系
IFileSystem
└── DefaultWebServerFileSystem
FSInitializeFileSystemOperation
└── DWSFSInitializeOperation
FSRequestPackageVersionOperation
└── DWSFSRequestPackageVersionOperation
FSLoadPackageManifestOperation
└── DWSFSLoadPackageManifestOperation
FSLoadBundleOperation
└── DWSFSLoadAssetBundleOperation
AsyncOperationBase
├── LoadWebServerCatalogFileOperation
├── RequestWebServerPackageVersionOperation
├── RequestWebServerPackageHashOperation
├── LoadWebServerPackageManifestOperation
└── LoadWebAssetBundleOperation (共享)
├── LoadWebNormalAssetBundleOperation
└── LoadWebEncryptAssetBundleOperation
BundleResult
└── AssetBundleResult
与 DefaultBuildinFileSystem 对比
| 特性 | DefaultWebServerFileSystem | DefaultBuildinFileSystem |
|---|---|---|
| 平台 | WebGL | 非 WebGL(移动端、PC) |
| 加载方式 | UnityWebRequest | AssetBundle.LoadFromFile |
| Catalog 系统 | ✅ 相同机制 | ✅ 相同机制 |
| 同步加载 | ❌ 不支持 | ✅ 支持 |
| 解包机制 | ❌ 无 | ✅ 有(Android APK) |
| 文件访问 | WWW 路径 | 本地文件路径 |
注意事项
- WebGL 专用:此文件系统专为 WebGL 平台设计,非 WebGL 平台应使用 DefaultBuildinFileSystem
- 仅支持 AssetBundle:不支持 RawBundle 类型的资源加载
- 不支持同步加载:WebGL 平台限制,
WaitForAsyncComplete()会直接返回失败 - Catalog 必需:初始化时必须成功加载 Catalog 文件,否则无法确定资源归属
- 同域加载:资源文件必须与 WebGL 构建在同一服务器上
- 部分方法未实现:
DownloadFileAsync、GetBundleFilePath、ReadBundleFileData、ReadBundleFileText会抛出异常 - 加密资源:加密资源需要配置
IWebDecryptionServices(Web 专用接口) - 路径缓存:内部使用字典缓存路径映射,提升重复访问性能