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 负责管理)
- 适用于热更、工具链、网络资源、编辑器工具等多种场景