赞
踩
本文是Asset资源加载,是文章(AssetBundle加载)的后续,读者可以先阅读上篇文章,再理解和使用这篇文章。
任何框架,都是从原理,到设计,然后实现,最后优化。
先讲讲原理。
Unity最通用的资源加载方式,就三种
Resources
资源加载(Runtime和Editor模式)AssetBundle
资源加载(Runtime和Editor模式)AssetDataBase
资源加载(Editor模式)大部分游戏,为了热更和效率考虑,都是——
AssetBundle
,极少数资源使用Resources
AssetDataBase
为主,Resources
为辅那么,我们的设计就要包含这三种加载方式。
Unity资源类型,按加载流程顺序,有三种
AssetBundle
资源以压缩包文件存在(Resources目录下资源打成包体后也是以ab格式存在)Asset
资源在内存中的存在格式GameObject
针对Prefab导出的Asset,可实例化Unity启动的时候,会将Resources目录下资源的ab加载到内存中,所以我们能直接使用Resources.Load()来加载资源。
针对AssetBundle
的加载,读者可以参阅AssetBundle同步异步引用计数资源加载管理器,下文中的
针对Asset
的加载,本文会作讲解,并提供整套方案和代码
针对GameObject
的加载,读者可以参阅Prefab加载自动化管理引用计数管理器。
依据上面的需求,我们来设计并实现一套Asset资源加载管理器吧。
Asset加载,要内部衔接多种资源加载方式,对外部隐藏底层资源加载逻辑。
内部主要管理三种加载方式
我们能在后续代码中看到很多如下的写法
public bool IsAssetExist(string _assetName)
{
#if UNITY_EDITOR && !TEST_AB
return EditorAssetLoadMgr.I.IsFileExist(_assetName);
#else
if (ResourcesLoadMgr.I.IsFileExist(_assetName)) return true;
return AssetBundleLoadMgr.I.IsABExist(_assetName);
#endif
}
宏UNITY_EDITOR
和TEST_AB
限定了Runtime和Editor模式,隐藏了内部逻辑,在Editor下也可以打开ab加载的开关,测试ab加载是否正确,逻辑是否正常。
EditorAssetLoadMgr
,ResourcesLoadMgr
和AssetBundleLoadMgr
都有通用的4个接口——IsFileExist
,LoadAsync
,LoadSync
和Unload
。
内部是对资源方式的封装,外部接口提供了类似的通用接口
当然,本文底部源码里,还有很多函数实现了特定功能,例如RemoveCallBack
,AddAsset
, AddAssetRef
等,这些只是功能性的函数,并不影响主体结构,就不展开讲了。
外部结构,内部结构都定义好了,我们开始实现逻辑。
要Update,先从队列开始
private Dictionary<string, AssetObject> _loadingList; //加载队列
private Dictionary<string, AssetObject> _loadedList; //完成队列
private Dictionary<string, AssetObject> _unloadList; //卸载队列
private List<AssetObject> _loadedAsyncList; //异步加载队列,延迟回调
private Queue<PreloadAssetObject> _preloadedAsyncList; //异步预加载,空闲时加载
主体就三个队列,加载队列
、完成队列
和销毁队列
,跟大部分开发者的资源管理大同小异
加载队列
完成队列
卸载队列
卸载队列
中延期卸载时间结束,真正卸载这边还有2个特殊队列,预加载队列
和异步加载队列
预加载队列
实现的是——当加载队列
为空情况下,取1个创建Asset单元放入加载队列
异步加载队列
实现的是——当资源已经加载完成,但需要异步回调时,延帧回调
具体代码实现,查看底部代码,具体就不详细说明啦。
TIP:为什么要有异步加载队列
?
我们可以考虑,我们异步加载一个资源,资源已存在,直接运行回调函数。
而这个时候,外部代码很可能还没设定好必要的逻辑,代码逻辑实际希望的是异步回调,在运行完逻辑设定之后。
所以,为了保证外部逻辑的正确性,就算资源已经加载好,也要异步回调,所以必须要有异步加载队列
。
先来看一下加载单元的数据结构
private class AssetObject
{
public string _assetName;
public int _lockCallbackCount; //记录回调当前数量,保证异步是下一帧回调
public List<AssetsLoadCallback> _callbackList = new List<AssetsLoadCallback>(); //回调函数
public
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。