06-02-源码-内置文件系统实现

源码-内置文件系统实现

篇章 :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)

相关推荐
SmalBox9 小时前
06-03-源码-下载系统(DownloadSystem)
unity3d·游戏开发
SmalBox2 天前
06-01-源码-文件系统体系(IFileSystem)
unity3d·游戏开发
狗凯之家源码网2 天前
H5 棋牌对战系统源码深度评测与实战分析
php·游戏开发
SmalBox3 天前
05-08-源码-缓存系统与内存管理
unity3d·游戏开发
雪庭4 天前
OCCT OCAF 实战
unity3d
SmalBox4 天前
05-07-源码-引用计数与资源生命周期
unity3d·游戏开发
雪庭4 天前
用 OCCT 造一只啤酒瓶:完整实录
unity3d
SmalBox5 天前
05-06-源码-异步操作体系(OperationSystem)
unity3d·游戏开发
侑虎科技5 天前
深度分析屏幕空间反射算法以及在URP中的实现(一)
unity3d