XASSET 5.1已经发布
XASSET 5.1为Unity项目提供了可以快速投入到生产环境中使用的具有更智能和灵活的资源分包、热更新机制和稳健高效的资源加载和内存管理的资源管理方案。它不仅可以服务于快速生产以及更有针对性的高效出包,更能在一些细微之处为你的项目保驾护航,具体请看:
XASSET Pro订阅指南zhuanlan.zhihu.com“XASSET杀人越货居家旅行必备框架。”,相比马三这天马行空的调侃,Aladdin更贴切的阐述了XASSET的一个实用价值:“老早之前我详细看过XASSET的代码,真的受益很大,之后的面试面试官问道的AB的问题,都能娓娓道来。“下面来说说XASSET 4.0:
XASSET 4.0 主要为有资源版本更新需求的Unity项目提供了一个更精简、高效、安全的资源管理方案。下图大致展示了4.0 版本的功能特点:
4.0 版本之前有专门写过一篇发布预告,没看过的的朋友可以先看看这里:
默默的奶爸:XASSET 4.0发布预告zhuanlan.zhihu.com4.0 的新特性:
- VFS自定义格式的文件读写支持,实现了一种非常高效的资源加密方案
- Versions支持任意格式的资源文件的版本管理,可以非常方便的对Wwise、Fmod等自定义格式的文件进行版本控制
- Updater支持大小包版本更新检查的程序
- Downloader支持断点续传、指纹校验、异常复原和并发数量配置的资源下载组件
- SearchPath更智能的寻址机制
- Lazy GC更高效的资源回收策略
VFS的重点说明
注:VFS使用文件流读取资源,初始化的时候会把索引表全部加载到内存,但不是把所有内容全部读取到内存。
了解更多
xasset入门指南 - TA养成记www.lfzxb.top资源管理的主要特点
- 支持开发模式和发布模式,可以按需打包,开发效率更高
- 基于引用计数管理资源对象生命周期,防止重复加载与轻易卸载,让程序更稳健
- 资源加载使用相对路径寻址,让业务代码不用接触 AssetBundle,降低开发门槛
- 没有循环依赖问题,资源加载底层对协程无依赖,经得住 Profiler 的检验
入门指南
资源加载与资源回收
核心接口
- Assets.Initialize 初始化
- Assets.LoadAsset(Async) 加载资源
- Assets.UnloadAsset 卸载资源
- Assets.LoadSceneAsync 加载场景
- Assets.UnloadScene 卸载场景
- Asset.Release 释放资源
初始化
加载资源前,需要先对系统进行成功初始化,下面是用协程进行初始化的代码示例:
IEnumerator Load()
{
/// 初始化
var init = Assets.Initialize();
yield return init;
if (! string.IsNullOrEmpty(init.error))
{
Debug.LogError(init.error);
yield break;
}
/// 初始化成功
......
}
初始化的底层是异步逻辑,调用 Assets.Initialize 后返回的是一个 AssetsInitRequest,在业务层除了使用协程阻塞等待初始化完成外,还可以用 AssetsInitRequest 的 completed 事件接受初始化完成的状态返回,写法类似下面将介绍的加载资源的逻辑,这里就不再一一列举了。
资源加载
使用 xasset 的 API 加载资源时,业务层不需要先加载资源的 AssetBundle 然后再从 AssetBundle 中加载需要的这个资源,而是使用资源在工程中以 Assets 开头的相对路径来寻址,具体可以参考下面的代码示例:
示例1:预制件加载
这里演示的是加载一个预制件:
var assetPath = "Assets/Demo/Prefabs/UIRoot.prefab";
Assets.LoadAssetAsync(assetPath, typeof(UnityEngine.Object)).completed += delegate(AssetRequest request)
{
if (! string.IsNullOrEmpty(request.error))
{
Debug.LogError(request.error);
return;
}
var go = Instantiate(request.asset);
go.name = request.asset.name;
/// 设置关注对象,当关注对象销毁时,回收资源
request.Require(go);
Destroy(go, 3);
/// 设置关注对象后,只需要释放一次
/// 这里如果之前没有调用 Require,下一帧这个资源就会被回收
request.Release();
};
注:对于 AssetRequest 的 Require 接口,不建议直接使用。这种机制是为了让一开始对资源内存管理没有做好规划的项目可以有一种改动较少然后又能稳妥有效回收资源的方案。使用后可能会对性能有一定影响:底层会在每帧轮询 Require 的对象是否为空,为空了就会释放对应的引用计数。
示例2:场景加载
这里演示的异步加载一个 Additive 的场景:
IEnumerator LoadSceneAsync()
{
var assetPath = "Assets/Demo/Scenes/Test.unity";
var sceneAsset = Assets.LoadSceneAsync(assetPath, true);
while(!sceneAsset.isDone)
{
Debug.Log(sceneAsset.progress);
yield return null;
}
yield return new WaitForSeconds(3);
/// 回收场景
Assets.UnloadScene(sceneAsset); // 还可以这样写 sceneAsset.Release()
}
示例3:加载没打AB的文本文件
这里演示的是加载一个版本文件,这个文件没有打 AssetBundle,此外 AudioClip 和 Texture 都有这种用法:
var url = "http://127.0.0.1:7888/OSX/versions.txt";
var asset = Assets.LoadAssetAsync(url, typeof(TextAsset));
asset.completed += delegate
{
if (asset.error != null)
{
OnError(asset.error);
return;
}
var text = asset.text;
Debug.Log(text)
/// ...
};
资源回收
xasset 内建了基于引用计数的资源内存管理机制,这种机制下,已经加载的资源不会重复加载,只是资源的引用计数会+1。如果资源的引用计数 > 1, 执行 AssetRequest.Release 也只是减少一次引用计数,当资源的引用计数为 0 的时候,这个资源就会被底层回收,所以写业务的时候 Load 和 Release 是需要配对使用的。
需要注意的是,一些人可能会对 Object.Instantiate 实例化的对象和 Assets.Load 出来的对象存在这样的误解:用Assets.Load 出来的 GameObject 在实例化后,直接 Destroy 实例化后的这个 GameObject,Assets.Load 的 GameObject 就会回收。
然而,实际情况并不是这样的。Object.Instantiate 的对象需要用 Object.Destroy 来回收,并且这个对象 Destroy 之后不等于相关的使用 Assets.Load 出来的资源会回收,对于 Assets.Load 出来的资源你只能通过对应的 Release 接口来回收。
资源打包与自动优化
使用 BuildRule 批量高效的进行资源打包分组
为了方便批量高效的进行资源分组,xasset 提供了 Assets/Apply Rule 的工具菜单来给要打包的资源设置打包规则,如下图:
上图中,Text/Prefab/Material/Controller/PNG/Asset/Scene 默认都是同类型的单个文件一组,而使用 Dir 这种规则则是会把同目录下不同类型的多个文件分配到一组,可以自己按需设置。如果针对 Assets/Demo/Prefab 选择 Apply Rule/Prefab,会在 Assets/BuildRules 文件中添加对应的打包规则,如下图:
针对 Assets/Demo/Prefabs 目录这条规则表示,该目录下的所有 prefab 在执行规则后,会按默认的方式生成对应的 AssetBundleName,即 prefabs/xxx, xxx 表示没有扩展名的预制件的名称小写。此外,也可以指定一个 AssetBundleName 给这个规则,指定后,和规则匹配的资源都会用这个名字设置对应的打包分组。
需要注意的是,使用 BuildRule 进行资源分组时,默认会对冗余的资源按最小粒度设置打包分组,即每个文件单独设置一个 AssetBundleName 来执行自动优化。具体细节可以参考 BuildRules.cs 的源码实现,这里就不再细说。
分组建议
如何合理的资源对资源设置AssetBundle分组?建议遵循这些原则:
- 同一时刻同时使用资源设置到一个AssetBundle
- 所有的shader设置到一个AssetBundle
- 同一个图集的所有图元设置到一个AssetBundle
- 尽可能的不使用内建的资源(Shader/Texture&Spritre etc.)
贡献成员
- yusjoel
- hemingfei
- veboys
- woshihuo12
- CatImmortal
- ZhangDi
- QuinShuai
- songtm
- woodelfLee
- LostEarth
- Coeur
- XINCGer
- 烟雨迷离半世殇
- 土豆
- JasonXuDeveloper
更多框架
- ET Unity3D Client And C# Server Framework
- Loxodon Framework MVVM Framework for Unity3D(C# & XLua)
- QFramework Your first K.I.S.S Unity 3D Framework
- TinaX Framework “开箱即用”的Unity独立游戏开发工具
- LuaProfiler-For-Unity Lua Profiler For Unity支持 XLua、SLua、ToLua