目录
正文
ResourceManager维护所有Loader,除了GameObjectLoader外,其他类型的资源都是一个路径一个Loader,由于预设可以复制,所以每复制一个预设,就创建一个GameObjectLoader,后面会详细介绍
下面先来个简单的例子,后面介绍GameObjectLoader例子。
假设此处有A/B/C三个地方同时加载"Assets/Works/Res/CS_Bytes/UIConfig.bytes"文件
假设加载UIConfig.bytes文件需要10秒钟时间,纯假设哈,加载二进制文件一般一帧就完成了。
下面的代码代表是A的代码,BC大概差不多
protected void Init<T>(string byteFileName) where T : TableBase
{
LoadAssetUtility.LoadTextAsset("CS_Bytes/UIConfig.bytes", LoadBytesCallback, true);
}
void LoadBytesCallback(AssetLoaderBase loader, bool state)
{
if (state == true)
{
TextFileLoader textLoader = (TextFileLoader)loader;
if (textLoader == null)
{
LogManager.LogError("TableCtrl textLoader is null: " + loader._resPath);
return;
}
Parser_Table(textLoader.GetBytes());
LoadTableState loadTable = FSMManager.Instance.GetState<LoadTableState>();
loadTable.LoadTableCallback();
}
else
LogManager.LogError("TableCtrl load table fail,_resPath: " + loader._resPath);
}
LoadAssetUtility代码:
//加载文本
//加载bytes/xml等文本文件也用该接口
public static TextFileLoader LoadTextAsset(string _url, OnLoadCallback callback, bool AutoRelease = false)
{
return ResourceManager.Instance.GetTextFileLoader(_url, callback, AutoRelease);
}
ResourceManager代码:
public TextFileLoader GetTextFileLoader(string url, OnLoadCallback callback, bool AutoRelease)
{
TextFileLoader loader = null;
if (_TextLoaderPool.ContainsKey(url))
loader = _TextLoaderPool[url];
else
{
loader = (TextFileLoader)_LoaderClassPool.GetAsset(typeof(TextFileLoader));
_TextLoaderPool[url] = (TextFileLoader)loader;
}
loader.LoadAsync(url, callback, typeof(TextAsset), AutoRelease);
return loader;
}
看ResourceManager代码也很好理解,如果_TextLoaderPool存在这个路径,则返回这个Loader,不要再重复实例化一个对象了,如果路径不存在,则创建一个Loader。假设第一个是A先加载,那么肯定会创建一个TextFileLoader,等BC也加载时,返回的就是A启动的那个TextFileLoader。
下面是AssetLoaderBase的代码,TextFileLoader继承AssetLoaderBase,上篇文章有讲,所有Loader都继承AssetLoaderBase
public void LoadAsync(string path, OnLoadCallback callback, Type t, bool autoRelease = false)
{
if (callback == null)
{
LogManager.LogError("load callback cant be null,load task return");
return;
}
//如果该Loader已有结果,则不重复开启加载任务
if (_LoadState == AssetLoadState.LoadSuccess ||_LoadState == AssetLoadState.LoadFailed)
{
callback(this,_LoadState == AssetLoadState.LoadSuccess);
return;
}
_prepareCallback += callback;
_resPath = path;
_LoadState = AssetLoadState.Loading;
LoadTaskManager.Instance.CreateLoadTask(this, OnLoadTaskFinish,t);
}
解读一下LoadAsync方法,callback是ABC传过来的加载结果回调方法,如果Loader已成功或失败,直接通知callback加载结果并return。我们的例子很显然没加载成功,代码会继续往下走。
_prepareCallback保存所有使用层回调,ABC的回调方法都会保存到这里
_resPath就是"CS_Bytes/UIConfig.bytes",请注意,我们所有资源都放在"Assets/Works/Res/"内,所以前缀路径写在LoadTask中,而不是发起加载的地方。
_LoadState = AssetLoadState.Loading;也比较好理解,设置加载状态
重点来了!!!!
LoadTaskManager.Instance.CreateLoadTask(this, OnLoadTaskFinish,t);里的OnLoadTaskFinish方法是TextFileLoader的,而不是基类的OnLoadTaskFinish方法。
基类里的OnLoadTaskFinish是抽象方法,压根没有实现,如下图
此时,ABC的加载回调已保存到这个TextFileLoader中,并开启了加载任务
提问:为何开启加载任务??
解答:请记住,Loader的作用是维护实例化后的资源,并不负责加载工作。
下一篇文章开启加载任务
Bundle卸载
资源卸载
19. 单纯卸载一个 AB 包解压的内存需要使用 Resources.UnloadAsset(Object assetToUnload);
- 20. 卸载全部的目前没有使用的解压的内存需要使用 Resources.UnloadUnusedAssets();
- 21. 单纯卸载一个 AB 包的解压的内存与压缩镜像内存 AssetBundle.Unload(true);
- 22. 卸载所有 AB 包目前没有在被使用的解压的内存与压缩镜像内存 AssetBundle.UnloadAllAssetBundles(false);
- 23. 卸载所有 AB 包的解压的内存与压缩镜像内存 AssetBundle.UnloadAllAssetBundles(true);