今天来详细介绍一下LoadManager、ResourceManager。LoadManager和ResourceManager主要负责框架的资源加载和管理,话不多说直接开始。
LoadManager主要的功能有:
LoadManager定义了多种加载方式的接口。加载单个资源、加载多个资源、加载场景。接口参数由资源名称、加载回调方法组成。代码如下:
/// 异步加载资源(单个)
/// 资源名称
/// 加载回调
public void LoadAssetAsync(string pAssetName, Action pLoadCallback = null)
{
LoadAsset(pAssetName, ELoadType.LoadAssetAsync, pLoadCallback);
}
/// 异步加载资源(多个)
/// Labals
/// 加载回调
public void LoadAssetsAsyc(string pLabelsName, Action pLoadCallback = null)
{
LoadAsset(pLabelsName, ELoadType.LoadAssetsAsyc, pLoadCallback);
}
/// 加载场景
///
///
public void LoadSceneAsyc(string pSceneName, Action pLoadCallback = null)
{
LoadAsset(pSceneName, ELoadType.LoadSceneAsyc, pLoadCallback);
}
不同的加载接口最终统一调用LoadAsset方法。LoadAsset负责Loader的创建与加载接口的调用。LoadAsset内通过调用Loader的加载接口进行资源加载。创建出来的Loader会被进行缓存,在加载完成后会移除对应的Loader。这样做的目的是避免同一资源重复。
为避免资源的重复加载,AsyncOperationHandle句柄会被保存在成员对象mHandleDictionay中,根据资源名称的HashCode来进行判断。如果已经加载过,则直接返回。
private Dictionary mHandleDictionay = new Dictionary();
private Dictionary mLoaderDictionary = new Dictionary();
private void LoadAsset(string pAssetName, ELoadType pLoadType, Action pLoadCallback = null)
{
int loaderId = pAssetName.GetHashCode();
if (mHandleDictionay.ContainsKey(loaderId))
{
pLoadCallback?.Invoke(true);
return;
}
Loader loader = CreateLoader(loaderId, pLoadCallback);
if (loader != null)
{
switch (pLoadType)
{
case ELoadType.LoadAssetAsync:
loader.LoadAssetAsync(pAssetName);
break;
case ELoadType.LoadAssetsAsyc:
loader.LoadAssetsAsync(pAssetName);
break;
case ELoadType.LoadSceneAsyc:
loader.LoadSceneAsync(pAssetName);
break;
}
}
}
private Loader CreateLoader(int loaderId, Action pLoadCallback = null)
{
Loader loader = null;
if (!mLoaderDictionary.ContainsKey(loaderId))
{
loader = new Loader(loaderId, pLoadCallback);
mLoaderDictionary.Add(loaderId, loader);
}
return loader;
}
接下来说一下Loader类。Loader类的主要功能有:
Loader类提供了多种对应Addressables加载资源的接口,加载单个资源、加载多个资源、加载场景。这些接口实现了Addressables对资源加载的调用。
资源加载完成后统一回调LoadComplete方法,LoadComplete会传入AsyncOperationHandle参数。加载成功后会在LoadManager移除Loader,在LoadManager添加AsyncOperationHandle,在ResourceManager添加资源等操作。
private class Loader
{
private int mLoaderId = -1;
private Action mLoadCallback = null;
private AsyncOperationHandle mAsyncOperationHandle = default;
public Loader(int loaderId, Action pLoadCallback = null)
{
mLoaderId = loaderId;
mLoadCallback = pLoadCallback;
}
#region AsyncOperationHandle.Completed
public void LoadAssetAsync(string pAssetName)
{
mAsyncOperationHandle = Addressables.LoadAssetAsync(pAssetName);
mAsyncOperationHandle.Completed += LoadComplete;
}
public void LoadAssetsAsync(string pLabelsKey)
{
mAsyncOperationHandle = Addressables.LoadAssetsAsync(pLabelsKey, null);
mAsyncOperationHandle.Completed += LoadComplete;
}
public void LoadSceneAsync(string pSceneName)
{
mAsyncOperationHandle = Addressables.LoadSceneAsync(pSceneName);
mAsyncOperationHandle.Completed += LoadComplete;
}
#endregion
private void LoadComplete(AsyncOperationHandle pHandle)
{
if (pHandle.Status == AsyncOperationStatus.Succeeded)
{
ManagerCollection.LoadManager.RemoveLoader(mLoaderId);
ManagerCollection.LoadManager.AddHandle(mLoaderId, pHandle);
ManagerCollection.ResourceManager.AddAsset(pHandle.Result);
mLoadCallback?.Invoke(true);
}
else if (pHandle.Status == AsyncOperationStatus.Failed)
{
Debug.LogWarning(pHandle.OperationException.Message);
mLoadCallback?.Invoke(false);
}
}
}
这里只展示了LoadManager的部分代码,关于完整代码,各位同学可以在文章最后获取Git下载工程。
ResourceManager主要功能有:
ResourceManager内定义了多个用于存储不同类型的Dictionary。
public class ResourceManager : ManagerBase
{
private Dictionary mAudioClipDictionary = new Dictionary();
private Dictionary mGameObjectDictionary = new Dictionary();
private Dictionary mTextAssetDictionary = new Dictionary();
public Dictionary mTextureDictionary = new Dictionary();
private Dictionary mSpriteDictionary = new Dictionary();
}
在LoadManager中提到过,加载成功后会调用ResourceManager的AddAsset方法进行资源的添加。AddAsset会根据资源类型,调用不同的添加方法,将资源保存到对应的Dictionary中。代码如下:
public void AddAsset(object pResult)
{
if (pResult is List)
{
List assetList = pResult as List;
for (int index = 0; index < assetList.Count; index++)
{
AddAsset(assetList[index]);
}
}
else
{
if (pResult is AudioClip)
AddAudioClip(pResult);
else if (pResult is GameObject)
AddGameObject(pResult);
else if (pResult is TextAsset)
AddTextAsset(pResult);
else if (pResult is Texture)
AddTexture(pResult);
else if (pResult is Sprite)
AddSprite(pResult);
}
}
private void AddAudioClip(object pAssetObject)
{
AudioClip audioClip = pAssetObject as AudioClip;
if (!mAudioClipDictionary.ContainsKey(audioClip.name))
mAudioClipDictionary.Add(audioClip.name, audioClip);
}
private void AddGameObject(object pAssetObject)
{
GameObject gameObj = pAssetObject as GameObject;
if (!mGameObjectDictionary.ContainsKey(gameObj.name))
mGameObjectDictionary.Add(gameObj.name, gameObj);
}
ResourceManager为每一个类型的资源定义了获取资源的方法。这里之所以为每一个类型都定义一个接口,是为了在调用ResourceManager的资源获取接口时,清楚的知道有哪些接口可以使用,并清楚的知道接口返回什么类型的结果。
public AudioClip GetAudioClip(string pAudioClipName)
{
if (mAudioClipDictionary.ContainsKey(pAudioClipName))
return mAudioClipDictionary[pAudioClipName];
else
return null;
}
public GameObject GetGameObject(string pGameObjectName)
{
if (mGameObjectDictionary.ContainsKey(pGameObjectName))
return mGameObjectDictionary[pGameObjectName];
else
return null;
}
最后就是移除资源的接口,与添加接口类似,每个类型的资源一一对应。
public void RemoveAsset(object pResult)
{
if (pResult is List)
{
List assetList = pResult as List;
for (int index = 0; index < assetList.Count; index++)
{
RemoveAsset(assetList[index]);
}
}
else
{
if (pResult is AudioClip)
RemoveAudioClip(pResult);
else if (pResult is GameObject)
RemoveGameObject(pResult);
else if (pResult is TextAsset)
RemoveTextAsset(pResult);
else if (pResult is Texture)
RemoveTexture(pResult);
else if (pResult is Sprite)
RemoveSprite(pResult);
}
}
private void RemoveAudioClip(object pAssetObject)
{
AudioClip audioClip = pAssetObject as AudioClip;
if (mAudioClipDictionary.ContainsKey(audioClip.name))
mAudioClipDictionary.Remove(audioClip.name);
}
private void RemoveGameObject(object pAssetObject)
{
GameObject gameObj = pAssetObject as GameObject;
if (mGameObjectDictionary.ContainsKey(gameObj.name))
mGameObjectDictionary.Remove(gameObj.name);
}
有关ResourceManager就先介绍到这里,这里只展示了部分代码,关于完整代码,各位同学可以在文章最后获取Git下载工程。
Release-Framework-Client客户端框架Git:https://gitee.com/huoyixian/release-framework-client
Manager模块介绍:https://blog.csdn.net/huoyixian/article/details/145613966