Provider 插件系统

Provider 系统是 ResLoad 的核心架构之一,决定了资源实际“从哪里来”以及“如何被加载”。
通过 Provider 插件式设计,ResLoad 可以轻松支持不同来源的资源,如:

  • Resources
  • 本地文件(file)
  • 网络资源(http/https)
  • 编辑器资源(editor)
  • 未来可拓展的 AB / Addressables
  • 自定义数据源(SQL、加密包、本地缓存等)

ResManager 只负责缓存、引用计数与调度,而 Provider 负责真正的加载行为


1. Provider 的职责

每个 Provider 需要实现 IResProvider 接口,提供以下能力:

T Load<T>(string path);
UniTask<T> LoadAsync<T>(string path);
bool Exists(string path);
void Unload(string path);
void Clear();
bool TryGetProgress(string path, out float progress);

职责说明:

方法作用
Load同步加载资源
LoadAsync异步加载资源
Exists判断资源是否存在
Unload执行底层卸载逻辑(如 AB.Unload)
Clear清理 Provider 缓存(非 Resources)
TryGetProgress返回异步加载的真实进度(如 UWR)

ResManager 不关心资源如何被读到内存,只通过 Provider 获取结果。


2. 前缀路由机制

ResLoad 根据路径前缀自动决定使用哪个 Provider:

前缀Provider说明
res://ResourcesProvider加载 Resources 文件夹
file://FileProvider加载本地磁盘文件
http:// / https://WebProvider加载网络内容
editor://EditorProvider编辑器资产加载(仅编辑器)
(无前缀)ResourcesProvider默认走 Resources

示例:

var prefab = ResManager.Instance.Load<GameObject>("UI/LoginPanel"); // 无前缀默认走Resources
var prefab = ResManager.Instance.Load<GameObject>("res://UI/LoginPanel");
var icon = await ResManager.Instance.LoadAsync<Texture2D>("http://server.com/icon.png");
var json = ResManager.Instance.Load<TextAsset>("file://C:/Data/config.json");

2.1 路径解析

ResManager 会执行:

  • 统一路径分隔符 /
  • 检查是否包含 :// 前缀
  • 分离 prefix 与真实路径
  • 若前缀不存在则默认使用 ResourcesProvider

例如:

fullPath: "http://server.com/img.png"
prefix:   "http"
path:     "server.com/img.png"

非法路径会自动报错(如 “://abc.png”)。


3. 内置 Provider 说明

ResLoad 内置四大 Provider,覆盖常用加载场景。

3.1 ResourcesProvider

使用 UnityEngine.Resources 加载。

支持内容:

  • 所有 Unity 内置资源类型(Prefab / Texture / AudioClip 等)

特点:

  • 同步和异步加载均可用

不支持真实加载进度(TryGetProgress 始终返回 false)

卸载必须通过 Resources.UnloadAsset,由 ResManager 执行

3.2 FileProvider(file://)

可加载本地磁盘文件。

支持类型:

  • TextAsset(.txt/.json/...)
  • Texture2D(jpg/png)
  • AudioClip(wav/mp3/ogg)
  • AssetBundle
  • byte[] 原始数据

特点:

  • 支持同步和异步加载
  • mp3/ogg 必须通过 UWR 加载
  • 无 Provider 自身缓存,清理操作为空

示例

var img = await ResManager.Instance.LoadAsync<Texture2D>("file://C:/icon.png");

3.3 WebProvider(http/https)

使用 UnityWebRequest 加载网络资源。

支持类型

  • Texture2D
  • AudioClip(wav/ogg/mp3)
  • AssetBundle
  • TextAsset
  • byte[]

特点:

  • 支持真实加载进度(通过 UWR AsyncOperation)
  • Req 失败时会自动报错
  • 不进行缓存(交由 ResManager 处理)

示例

var tex = await ResManager.Instance.LoadAsync<Texture2D>("https://cdn/game/icon.png");

3.4 EditorProvider(editor://)

仅在编辑器下启用,基于 AssetDatabase。

用途:

  • 编辑器工具窗口
  • Inspector 自定义绘制
  • 预览图集与 UI
  • 不参与构建

特点:

  • 仅支持同步加载(异步为模拟)
  • 自动补全常见扩展名(.png/.prefab/.mat 等)
  • 无缓存

示例

var icon = ResManager.Instance.Load<Texture2D>("editor://Icons/Close");

4. 自定义 Provider(扩展能力)

开发者可以实现自己的 Provider 来接入:

  • 加密二进制资源
  • SQLite 或本地数据库
  • AB 管理框架(YooAsset / Addressables)
  • 云端 CDN 热更系统
  • ProtoBuf / 自定义二进制容器

模板示例

public class CustomProvider : IResProvider
{
    public T Load<T>(string path) where T : Object
    {
        // 读取文件 / 数据库 / 缓存 ...
        return obj as T;
    }

    public async UniTask<T> LoadAsync<T>(string path) where T : Object
    {
        await UniTask.Yield();
        return Load<T>(path);
    }

    public void Unload(string path)
    {
        // 可选:释放 AB、缓存、句柄等
    }

    public void Clear()
    {
        // 可选:清空 Provider 自己的缓存
    }

    public bool Exists(string path)
    {
        // 检查是否存在
        return true;
    }

    public bool TryGetProgress(string path, out float progress)
    {
        progress = 0f;
        return false;
    }
}

注册自定义 Provider:

ResManager.Instance.AddProvider("custom", new CustomProvider());

使用方式:

var data = await ResManager.Instance.LoadAsync<TextAsset>("custom://mydata");

5. Provider 系统工作流程图

用户调用 Load / LoadAsync
           │
           ▼
     ResManager.ParsePath
           │
           ▼
 根据 prefix 选择 Provider
           │
           ▼
Provider.Load / LoadAsync 实际加载
           │
           ▼
   ResInfo<T> 写入缓存 / 引用计数管理
           │
           ▼
 返回结果(同步 / await / callback / 句柄)

6. 小结

Provider 系统使 ResLoad 具备:

  • 完整的可扩展能力(几乎能接入任何数据源)
  • 强大的跨平台灵活性
  • 清晰的职责分离(Provider 负责加载,ResManager 负责管理)
  • 适用于热更、工具链、网络资源、编辑器工具等多种场景