AssetBundle资源包加载器 介绍
它是资源三大加载器之一,一个非常好用的AssetBundle加载器,也可以直接通过异步的资源加载函数直接加载资源,资源加载函数会自动去查找资源所在的AB包,自动加载AB,它支持多种加载方式,File模式加载、UnityWebRequest加载,AssetBundle方式加载(在Unity5.6以上版本,请不要使用WWW加载器,它会产生内存峰值)。支持加密AB包(只建议加密敏感资源,因为会影响性能)。同时它也绕开了Unity3D早期版本的一些bug,比如多个协程并发加载同一个资源,在android系统会出错。它的冗余分析是通过解包AssetBundle进行的,这比在编辑器模式下分析的冗余更准确。
AssetBundle资源包加载器 完整代码
//AssetBundle资源包加载器
public class AssetBundleLoaderRoutine
{
//当前的资源包信息
private AssetBundleInfoEntity m_CurrAssetBundleInfo;
//资源包创建请求
private AssetBundleCreateRequest m_CurrAssetBundleCreateRequest;
//资源包创建请求(加载进度)更新
public Action<float> OnAssetBundleCreateUpdate;
//资源包加载完毕
public Action<AssetBundle> OnLoadAssetBundleComplete;
#region 加载资源包 LoadAssetBundle
public void LoadAssetBundleAsync(byte[] buffer)
{
if (m_CurrAssetBundleInfo.IsEncrypt)
{
//AssetBundle资源包加载器
public class AssetBundleLoaderRoutine
{
//当前的资源包信息
private AssetBundleInfoEntity m_CurrAssetBundleInfo;
//资源包创建请求
private AssetBundleCreateRequest m_CurrAssetBundleCreateRequest;
//资源包创建请求(加载进度)更新
public Action<float> OnAssetBundleCreateUpdate;
//资源包加载完毕
public Action<AssetBundle> OnLoadAssetBundleComplete;
#region 加载资源包 LoadAssetBundle
public void LoadAssetBundleAsync(byte[] buffer)
{
if (m_CurrAssetBundleInfo.IsEncrypt)
{
buffer = SecurityUtil.Xor(buffer);
}
//从内存加载assbundle(把byte[] 解释成AssetBundle类型)
m_CurrAssetBundleCreateRequest = AssetBundle.LoadFromMemoryAsync(buffer);
}
//加载资源包
public void LoadAssetBundle(string assetBundlePath)
{
m_CurrAssetBundleInfo = GameEntry.Resource.ResManager.GetCDNAssetBundleInfo(assetBundlePath);
//检查文件在可写区是否存在
bool isExistInLocal = GameEntry.Resource.ResManager.LocalAssetsManager.CheckFileExists(assetBundlePath);
//如果资源包存在于可写区 并且 没加密
if (isExistInLocal && !m_CurrAssetBundleInfo.IsEncrypt)
{
m_CurrAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(string.Format("{0}/{1}", Application.persistentDataPath, assetBundlePath));
}
//不存在 或者 加密了
else
{
byte[] buffer = GameEntry.Resource.ResManager.LocalAssetsManager.GetFileBuffer(assetBundlePath);
//本地无此文件
if (buffer == null)
{
//从只读区获取
GameEntry.Resource.ResManager.StreamingAssetsManager.ReadAssetBundle(assetBundlePath, (byte[] streamingFileBuffer) =>
{
//如果只读区也找不到,说明只读区没有
if (streamingFileBuffer == null)
{
GameEntry.Download.BeginDownloadSingle(assetBundlePath, onComplete: (string fileUrl) =>
{
buffer = GameEntry.Resource.ResManager.LocalAssetsManager.GetFileBuffer(fileUrl);
LoadAssetBundleAsync(buffer);
});
}
else
{
LoadAssetBundleAsync(streamingFileBuffer);
}
});
}
else
{
LoadAssetBundleAsync(buffer);
}
}
}
#endregion
//更新资源包请求(更新资源包加载)
private void UpdateAssetBundleCreateRequest()
{
if (null == m_CurrAssetBundleCreateRequest)
return;
if (m_CurrAssetBundleCreateRequest.isDone)
{
//下载完成,执行回调,通知被观察者
AssetBundle assetBundle = m_CurrAssetBundleCreateRequest.assetBundle;
if (assetBundle != null)
{
GameEntry.Log(LogCategory.Resource,"资源包=>{0} 加载完毕",m_CurrAssetBundleInfo.AssetBundleName);
//一定要早点reset,不然会出问题
Reset();
OnLoadAssetBundleComplete?.Invoke(assetBundle);
}
else
{
GameEntry.LogError("资源包=>{0} 加载失败",m_CurrAssetBundleInfo.AssetBundleName);
Reset();
OnLoadAssetBundleComplete?.Invoke(null);
}
}
else
{
//没有下载完成,回调加载进度
if (null != OnAssetBundleCreateUpdate)
{
OnAssetBundleCreateUpdate(m_CurrAssetBundleCreateRequest.progress);
}
}
}
public void OnUpdate()
{
UpdateAssetBundleCreateRequest();
}
//重置
public void Reset()
{
m_CurrAssetBundleCreateRequest = null;
}
} buffer = SecurityUtil.Xor(buffer);
}
//从内存加载assbundle(把byte[] 解释成AssetBundle类型)
m_CurrAssetBundleCreateRequest = AssetBundle.LoadFromMemoryAsync(buffer);
}
//加载资源包
public void LoadAssetBundle(string assetBundlePath)
{
m_CurrAssetBundleInfo = GameEntry.Resource.ResManager.GetCDNAssetBundleInfo(assetBundlePath);
//检查文件在可写区是否存在
bool isExistInLocal = GameEntry.Resource.ResManager.LocalAssetsManager.CheckFileExists(assetBundlePath);
//如果资源包存在于可写区 并且 没加密
if (isExistInLocal && !m_CurrAssetBundleInfo.IsEncrypt)
{
m_CurrAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(string.Format("{0}/{1}", Application.persistentDataPath, assetBundlePath));
}
//不存在 或者 加密了
else
{
byte[] buffer = GameEntry.Resource.ResManager.LocalAssetsManager.GetFileBuffer(assetBundlePath);
//本地无此文件
if (buffer == null)
{
//从只读区获取
GameEntry.Resource.ResManager.StreamingAssetsManager.ReadAssetBundle(assetBundlePath, (byte[] streamingFileBuffer) =>
{
//如果只读区也找不到,说明只读区没有
if (streamingFileBuffer == null)
{
GameEntry.Download.BeginDownloadSingle(assetBundlePath, onComplete: (string fileUrl) =>
{
buffer = GameEntry.Resource.ResManager.LocalAssetsManager.GetFileBuffer(fileUrl);
LoadAssetBundleAsync(buffer);
});
}
else
{
LoadAssetBundleAsync(streamingFileBuffer);
}
});
}
else
{
LoadAssetBundleAsync(buffer);
}
}
}
#endregion
//更新资源包请求(更新资源包加载)
private void UpdateAssetBundleCreateRequest()
{
if (null == m_CurrAssetBundleCreateRequest)
return;
if (m_CurrAssetBundleCreateRequest.isDone)
{
//下载完成,执行回调,通知被观察者
AssetBundle assetBundle = m_CurrAssetBundleCreateRequest.assetBundle;
if (assetBundle != null)
{
GameEntry.Log(LogCategory.Resource,"资源包=>{0} 加载完毕",m_CurrAssetBundleInfo.AssetBundleName);
//一定要早点reset,不然会出问题
Reset();
OnLoadAssetBundleComplete?.Invoke(assetBundle);
}
else
{
GameEntry.LogError("资源包=>{0} 加载失败",m_CurrAssetBundleInfo.AssetBundleName);
Reset();
OnLoadAssetBundleComplete?.Invoke(null);
}
}
else
{
//没有下载完成,回调加载进度
if (null != OnAssetBundleCreateUpdate)
{
OnAssetBundleCreateUpdate(m_CurrAssetBundleCreateRequest.progress);
}
}
}
public void OnUpdate()
{
UpdateAssetBundleCreateRequest();
}
//重置
public void Reset()
{
m_CurrAssetBundleCreateRequest = null;
}
}