源码-内置文件系统实现
篇章 :06-源码深度-文件系统与下载模块 阅读时间 :约 25 分钟 前置知识:了解 IFileSystem 接口
一、引言
本章将深入解析 YooAsset 内置文件系统(DefaultBuildinFileSystem、DefaultCacheFileSystem、DefaultDeliveryFileSystem)的源码实现。这些内置文件系统是 YooAsset 的默认实现,覆盖了主流平台的需求。深入理解这些实现,有助于开发者在遇到跨平台问题时进行调试和优化。
YooAsset 的内置文件系统针对不同平台的特点进行了优化,本章将详细解析这些优化策略。
二、StreamingAssetsFileSystem 实现
2.1 StreamingAssetsFileSystem 概述
StreamingAssetsFileSystem 是基于 Unity StreamingAssets 的文件系统:
特点:
- 用于访问打包在游戏包体内的资源
- 不同平台的访问方式不同
- 资源是只读的
实现位置:
YooAsset/Runtime/FileSystem/DefaultBuildinFileSystem/DefaultBuildinFileSystem.cs
2.2 跨平台实现
csharp
public class DefaultBuildinFileSystem : FileSystemBase
{
public override bool Exists(string filePath)
{
string fullPath = Path.Combine(RootDirectory, filePath);
#if UNITY_EDITOR
return File.Exists(fullPath);
#elif UNITY_ANDROID
return AndroidExists(fullPath);
#elif UNITY_IOS
return File.Exists(fullPath);
#elif UNITY_WEBGL
return WebGLExists(fullPath);
#else
return File.Exists(fullPath);
#endif
}
}
跨平台条件编译详解:
使用 #if 条件编译处理不同平台的差异。
Editor 平台详解:
Editor 平台下直接使用 File.Exists 检查文件。
Android 平台详解:
Android 平台下需要使用 UnityWebRequest 访问 jar 协议。
iOS 平台详解:
iOS 平台下直接使用 File.Exists 检查文件。
WebGL 平台详解:
WebGL 平台下需要使用 UnityWebRequest 访问 HTTP 协议。
2.3 Android 平台实现
csharp
private bool AndroidExists(string filePath)
{
using (UnityWebRequest request = UnityWebRequest.Head(filePath))
{
request.SendWebRequest();
while (!request.isDone) { }
return request.result == UnityWebRequest.Result.Success;
}
}
UnityWebRequest.Head 详解:
使用 HEAD 请求检查文件是否存在,HEAD 请求不下载文件内容。
同步等待详解:
使用 while 循环同步等待请求完成(在实际代码中应使用异步方式)。
2.4 WebGL 平台实现
csharp
private bool WebGLExists(string filePath)
{
using (UnityWebRequest request = UnityWebRequest.Head(filePath))
{
var asyncOp = request.SendWebRequest();
while (!asyncOp.isDone) { }
return request.result == UnityWebRequest.Result.Success;
}
}
WebGL 限制详解:
WebGL 平台不支持本地文件访问,所有文件都需要通过 HTTP 访问。
Service Worker 缓存详解:
WebGL 平台可以使用 Service Worker 实现本地缓存。
三、PersistentFileSystem 实现
3.1 PersistentFileSystem 概述
PersistentFileSystem 是基于 Unity persistentDataPath 的文件系统:
特点:
- 用于持久化存储已下载的资源
- 跨平台兼容性好
- 支持读写操作
实现位置:
YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/DefaultCacheFileSystem.cs
3.2 跨平台路径
csharp
public class DefaultCacheFileSystem : FileSystemBase
{
public override void OnCreate(string packageName, string rootDirectory)
{
base.OnCreate(packageName, rootDirectory);
// 确保缓存目录存在
if (!Directory.Exists(RootDirectory))
Directory.CreateDirectory(RootDirectory);
}
private string GetFullPath(string filePath)
{
return Path.Combine(RootDirectory, filePath);
}
}
持久化路径详解:
- iOS:
Application.persistentDataPath=<Application>/Documents/ - Android:
Application.persistentDataPath=/storage/emulated/0/Android/data/<package>/files - Windows:
%USERPROFILE%/AppData/LocalLow/<company>/<product>
目录创建详解:
在 OnCreate 时确保缓存目录存在。
3.3 读写实现
csharp
public override byte[] ReadFile(string filePath)
{
string fullPath = GetFullPath(filePath);
if (File.Exists(fullPath))
return File.ReadAllBytes(fullPath);
return null;
}
public override bool WriteFile(string filePath, byte[] fileData)
{
string fullPath = GetFullPath(filePath);
string directory = Path.GetDirectoryName(fullPath);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
File.WriteAllBytes(fullPath, fileData);
return true;
}
读取实现详解:
使用 File.ReadAllBytes 读取整个文件到内存。
写入实现详解:
使用 File.WriteAllBytes 写入文件。先创建目录再写入文件。
3.4 性能优化
csharp
public override byte[] ReadFile(string filePath)
{
string fullPath = GetFullPath(filePath);
if (File.Exists(fullPath))
{
// 使用 FileShare.Read 允许其他进程读取
using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (BinaryReader reader = new BinaryReader(fs))
{
return reader.ReadBytes((int)fs.Length);
}
}
return null;
}
流式读取详解:
使用 FileStream 流式读取文件,避免大文件占用过多内存。
FileShare 详解:
使用 FileShare.Read 允许其他进程同时读取文件。
四、WebFileSystem 实现
4.1 WebFileSystem 概述
WebFileSystem 是基于 Web 平台的文件系统:
特点:
- 用于 WebGL 平台
- 不支持本地文件访问
- 通过 HTTP 访问远程资源
实现位置:
YooAsset/Runtime/FileSystem/DefaultDeliveryFileSystem/DefaultDeliveryFileSystem.cs
4.2 HTTP 访问实现
csharp
public class DefaultDeliveryFileSystem : FileSystemBase
{
public override byte[] ReadFile(string filePath)
{
string url = GetFileURL(filePath);
using (UnityWebRequest request = UnityWebRequest.Get(url))
{
var asyncOp = request.SendWebRequest();
while (!asyncOp.isDone) { }
if (request.result == UnityWebRequest.Result.Success)
return request.downloadHandler.data;
return null;
}
}
private string GetFileURL(string filePath)
{
return Path.Combine(RootDirectory, filePath).Replace("\\", "/");
}
}
HTTP GET 详解:
使用 UnityWebRequest.Get 发起 HTTP GET 请求。
URL 构造详解:
将 RootDirectory 和 filePath 组合成完整的 URL。
4.3 HTTP 缓存
csharp
public class WebCacheFileSystem : DefaultDeliveryFileSystem
{
private Dictionary<string, byte[]> _memoryCache = new Dictionary<string, byte[]>();
public override byte[] ReadFile(string filePath)
{
if (_memoryCache.TryGetValue(filePath, out var data))
return data;
data = base.ReadFile(filePath);
if (data != null)
_memoryCache[filePath] = data;
return data;
}
}
内存缓存详解:
使用 Dictionary 实现内存缓存,避免重复 HTTP 请求。
缓存限制详解:
内存缓存有大小限制,需要 LRU 策略管理。
4.4 IndexedDB 缓存(WebGL)
csharp
public class IndexedDBCache
{
public void Save(string key, byte[] data);
public byte[] Load(string key);
public void Delete(string key);
}
IndexedDB 详解:
IndexedDB 是浏览器提供的本地数据库,可用于持久化缓存。
应用场景详解:
WebGL 平台下使用 IndexedDB 实现持久化缓存。
五、RawFileFileSystem 实现
5.1 RawFileFileSystem 概述
RawFileFileSystem 是基于 Resources 目录的文件系统:
特点:
- 用于访问 Resources 目录下的资源
- 资源会被打包到安装包
- 不需要打 AssetBundle
实现位置:
YooAsset/Runtime/FileSystem/RawFileSystem/RawFileSystem.cs
5.2 Resources 加载实现
csharp
public class RawFileSystem : FileSystemBase
{
public override byte[] ReadFile(string filePath)
{
TextAsset textAsset = Resources.Load<TextAsset>(filePath);
if (textAsset != null)
return textAsset.bytes;
return null;
}
public override string ReadFileText(string filePath)
{
TextAsset textAsset = Resources.Load<TextAsset>(filePath);
if (textAsset != null)
return textAsset.text;
return null;
}
}
Resources.Load 详解:
使用 Resources.Load 加载 Resources 目录下的资源。
TextAsset 详解:
TextAsset 是 Unity 的文本资源类型,可以获取字节或文本。
5.3 RawFile 的应用
配置文件:
将 JSON、XML 等配置文件放在 Resources 目录。
小型资源:
将小图片、音频片段等放在 Resources 目录。
本地化文件:
将本地化字符串文件放在 Resources 目录。
六、文件系统错误处理
6.1 错误类型
文件系统可能遇到以下错误:
- 文件不存在
- 读取失败
- 写入失败
- 权限不足
- 磁盘空间不足
6.2 错误处理实现
csharp
public override byte[] ReadFile(string filePath)
{
string fullPath = GetFullPath(filePath);
if (!File.Exists(fullPath))
{
Debug.LogWarning($"File not found: {fullPath}");
return null;
}
try
{
return File.ReadAllBytes(fullPath);
}
catch (Exception ex)
{
Debug.LogError($"Failed to read file {fullPath}: {ex.Message}");
return null;
}
}
文件不存在处理详解:
返回 null,调用方根据 null 处理。
异常捕获详解:
使用 try-catch 捕获读取异常。
6.3 重试机制
csharp
public override byte[] ReadFileWithRetry(string filePath, int maxRetries = 3)
{
for (int i = 0; i < maxRetries; i++)
{
try
{
return ReadFile(filePath);
}
catch (Exception ex)
{
if (i == maxRetries - 1) throw;
Thread.Sleep(100);
}
}
return null;
}
重试策略详解:
失败时重试一定次数。
退避策略详解:
每次重试前等待一段时间。
七、总结
本章深入解析了 YooAsset 内置文件系统的实现,包括:
- StreamingAssetsFileSystem:基于 StreamingAssets 的文件系统,跨平台实现
- PersistentFileSystem:基于 persistentDataPath 的持久化文件系统
- WebFileSystem:基于 HTTP 的 Web 平台文件系统
- RawFileFileSystem:基于 Resources 目录的文件系统
- 错误处理:错误类型、错误处理实现、重试机制
通过深入理解这些实现,开发者可以更好地使用和优化 YooAsset 的文件系统。
下一篇 :下载系统(DownloadSystem)