编辑器移动路径需要修改
以前场景的后缀用的是.unity3d,现在统一改为assetbundle
以前生成版本文件的时候不包含扩展名name,现在把扩展名加了回来。版本文件包含扩展名
下面开始加载资源包
资源包加载器
资源包加载器
namespace YouYou
{
/// <summary>
/// 资源包加载器
/// </summary>
public class AssetBundleLoaderRoutine
{
/// <summary>
/// 当前的资源包信息
/// </summary>
private AssetBundleInfoEntity m_CurrAssetBundleInfo;
/// <summary>
/// 资源包创建请求
/// </summary>
private AssetBundleCreateRequest m_CurrAssetBundleCreateRequest;
/// <summary>
/// 资源包创建请求更新
/// </summary>
public Action<float> OnAssetBundleCreateUpdate;
/// <summary>
/// 加载资源包完毕
/// </summary>
public Action<AssetBundle> OnLoadAssetBundleComplete;
#region LoadAssetBundle 加载资源包
/// <summary>
/// 加载资源包
/// </summary>
public void LoadAssetBundle(string assetBundlePath)
{
m_CurrAssetBundleInfo = GameEntry.Resource.ResourceManager.GetAssetBundleInfo(assetBundlePath);
//检查文件在可写区是否存在
bool isExistsInLocal = GameEntry.Resource.ResourceManager.LocalAssetsManager.CheckFileExists(assetBundlePath);
if (isExistsInLocal && !m_CurrAssetBundleInfo.IsEncrypt)
{
//如果资源包存在于可写区 并且没有加密
m_CurrAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(string.Format("{0}/{1}", Application.persistentDataPath, assetBundlePath));
}
else
{
byte[] buffer = GameEntry.Resource.ResourceManager.LocalAssetsManager.GetFileBuffer(assetBundlePath);
if (buffer == null)
{
//如果可写区没有 那么就从只读区获取
GameEntry.Resource.ResourceManager.StreamingAssetsManager.ReadAssetBundle(assetBundlePath, (byte[] buff) =>
{
if (buff == null)
{
//如果只读区也没有,从CDN下载
GameEntry.Download.BeginDownloadSingle(assetBundlePath, onComplete: (string fileUrl) =>
{
buffer = GameEntry.Resource.ResourceManager.LocalAssetsManager.GetFileBuffer(fileUrl);
LoadAssetBundleAsync(buffer);
});
}
else
{
//从只读区加载资源包
LoadAssetBundleAsync(buff);
}
});
}
else
{
//从可写区加载资源包
LoadAssetBundleAsync(buffer);
}
}
}
/// <summary>
/// 异步加载资源包
/// </summary>
/// <param name="buffer"></param>
private void LoadAssetBundleAsync(byte[] buffer)
{
if (m_CurrAssetBundleInfo.IsEncrypt)
{
//如果资源包是加密的,则解密
buffer = SecurityUtil.Xor(buffer);
}
m_CurrAssetBundleCreateRequest = AssetBundle.LoadFromMemoryAsync(buffer);
}
#endregion
/// <summary>
/// 重置
/// </summary>
public void Reset()
{
m_CurrAssetBundleCreateRequest = null;
}
/// <summary>
/// 更新
/// </summary>
public void OnUpdate()
{
UpdateAssetBundleCreateRequest();
}
#region UpdateAssetBundleCreateRequest 更新资源包请求
/// <summary>
/// 更新资源包请求
/// </summary>
private void UpdateAssetBundleCreateRequest()
{
if (m_CurrAssetBundleCreateRequest != null)
{
if (m_CurrAssetBundleCreateRequest.isDone)
{
AssetBundle assetBundle = m_CurrAssetBundleCreateRequest.assetBundle;
if (assetBundle != null)
{
GameEntry.Log(LogCategory.Resource, "资源包=>{0} 加载完毕", m_CurrAssetBundleInfo.AssetBundleName);
Reset();//一定要早点Reset
if (OnLoadAssetBundleComplete != null) OnLoadAssetBundleComplete(assetBundle);
}
else
{
GameEntry.LogError("资源包=>{0} 加载失败", m_CurrAssetBundleInfo.AssetBundleName);
Reset();//一定要早点Reset
if (OnLoadAssetBundleComplete != null) OnLoadAssetBundleComplete(null);
}
}
else
{
//加载进度
if (OnAssetBundleCreateUpdate != null) OnAssetBundleCreateUpdate(m_CurrAssetBundleCreateRequest.progress);
}
}
}
#endregion
}
}
当前资源包信息
namespace YouYou
{
/// <summary>
/// AssetBundle版本文件信息实体
/// </summary>
public class AssetBundleInfoEntity
{
/// <summary>
/// 资源包名称
/// </summary>
public string AssetBundleName;
/// <summary>
/// MD5码
/// </summary>
public string MD5;
/// <summary>
/// 文件大小(字节)
/// </summary>
public ulong Size;
/// <summary>
/// 是否初始数据
/// </summary>
public bool IsFirstData;
/// <summary>
/// 是否已经加密
/// </summary>
public bool IsEncrypt;
}
}
获取CDN上的资源包信息
异步加载资源包
/// <summary>
/// 异步加载资源包
/// </summary>
/// <param name="buffer"></param>
private void LoadAssetBundleAsync(byte[] buffer)
{
if (m_CurrAssetBundleInfo.IsEncrypt)
{
//如果资源包是加密的,则解密
buffer = SecurityUtil.Xor(buffer);
}
m_CurrAssetBundleCreateRequest = AssetBundle.LoadFromMemoryAsync(buffer);
}
异步加载返回的AssetBundleCreateRequest
更新资源包请求
#region UpdateAssetBundleCreateRequest 更新资源包请求
/// <summary>
/// 更新资源包请求
/// </summary>
private void UpdateAssetBundleCreateRequest()
{
if (m_CurrAssetBundleCreateRequest != null)
{
//请求加载完毕,资源加载完了
if (m_CurrAssetBundleCreateRequest.isDone)
{
AssetBundle assetBundle = m_CurrAssetBundleCreateRequest.assetBundle;
if (assetBundle != null)
{
GameEntry.Log(LogCategory.Resource, "资源包=>{0} 加载完毕", m_CurrAssetBundleInfo.AssetBundleName);
Reset();//一定要早点Reset
//资源包加载完毕的回调
if (OnLoadAssetBundleComplete != null) OnLoadAssetBundleComplete(assetBundle);
}
else
{
GameEntry.LogError("资源包=>{0} 加载失败", m_CurrAssetBundleInfo.AssetBundleName);
Reset();//一定要早点Reset
if (OnLoadAssetBundleComplete != null) OnLoadAssetBundleComplete(null);
}
}
else
{
//加载进度
if (OnAssetBundleCreateUpdate != null)
{
OnAssetBundleCreateUpdate(m_CurrAssetBundleCreateRequest.progress);
}
}
}
}
#endregion
加载器的使用
/// <summary>
/// 资源包加载器链表
/// </summary>
private LinkedList<AssetBundleLoaderRoutine> m_AssetBundleLoaderList;
/// <summary>
/// 资源加载器链表
/// </summary>
private LinkedList<AssetLoaderRoutine> m_AssetLoaderList;
加载器可能反复使用
对象池组件初始化的时候设置数量
加载资源包
#region LoadAssetBundle 加载资源包
/// <summary>
/// 加载中的Bundle
/// </summary>
private Dictionary<string, LinkedList<Action<AssetBundle>>> m_LoadingAssetBundle = new Dictionary<string, LinkedList<Action<AssetBundle>>>();
/// <summary>
/// 加载资源包
/// </summary>
/// <param name="assetbundlePath"></param>
/// <param name="onUpdate"></param>
/// <param name="onComplete"></param>
public void LoadAssetBundle(string assetbundlePath, Action<float> onUpdate = null, Action<AssetBundle> onComplete = null)
{
//Debug.LogError("加载资源包" + assetbundlePath);
//1.判断资源包是否存在于AssetBundlePool
ResourceEntity assetBundleEntity = GameEntry.Pool.PoolManager.AssetBundlePool.Spawn(assetbundlePath);
if (assetBundleEntity != null)
{
//Debug.Log("资源包在资源池中存在 从资源池中加载AssetBundle");
AssetBundle assetBundle = assetBundleEntity.Target as AssetBundle;
if (onComplete != null) onComplete(assetBundle);
return;
}
//2.判断Bundle是否加载到一半,防止高并发导致重复加载
LinkedList<Action<AssetBundle>> lst = null;
if (m_LoadingAssetBundle.TryGetValue(assetbundlePath, out lst))
{
//如果Bundle已经在加载中, 把委托加入对应的链表 然后直接return;
lst.AddLast(onComplete);
return;
}
else
{
//如果Bundle还没有开始加载, 把委托加入对应的链表 然后开始加载
lst = GameEntry.Pool.DequeueClassObject<LinkedList<Action<AssetBundle>>>();
lst.AddLast(onComplete);
m_LoadingAssetBundle[assetbundlePath] = lst;
}
//加载器从池中取
AssetBundleLoaderRoutine routine = GameEntry.Pool.DequeueClassObject<AssetBundleLoaderRoutine>();
if (routine == null)
{
routine = new AssetBundleLoaderRoutine();
}
//加入链表开始循环
m_AssetBundleLoaderList.AddLast(routine);
//加载资源包
routine.LoadAssetBundle(assetbundlePath);
//资源包加载 进行中 回调
routine.OnAssetBundleCreateUpdate = (float progress) =>
{
if (onUpdate != null) onUpdate(progress);
};
//资源包加载 结束 回调
routine.OnLoadAssetBundleComplete = (AssetBundle assetbundle) =>
{
//资源包取池
assetBundleEntity = GameEntry.Pool.DequeueClassObject<ResourceEntity>();
assetBundleEntity.ResourceName = assetbundlePath;
assetBundleEntity.IsAssetBundle = true;
assetBundleEntity.Target = assetbundle;
//资源包注册到资源池
GameEntry.Pool.PoolManager.AssetBundlePool.Register(assetBundleEntity);
for (LinkedListNode<Action<AssetBundle>> curr = lst.First; curr != null; curr = curr.Next)
{
if (curr.Value != null) curr.Value(assetbundle);
}
//资源加载完毕后
lst.Clear();//必须清空
GameEntry.Pool.EnqueueClassObject(lst);
m_LoadingAssetBundle.Remove(assetbundlePath);//从加载中的Bundle的Dic 移除
//结束循环 回池,从链表中移除掉
m_AssetBundleLoaderList.Remove(routine);
//加载器回池
GameEntry.Pool.EnqueueClassObject(routine);
};
}
#endregion
/// <summary>
/// 异步加载数据表
/// </summary>
public void LoadDataTableAsync()
{
#if ASSETBUNDLE
GameEntry.Resource.ResourceLoaderManager.LoadAssetBundle(ConstDefine.DataTableAssetBundlePath, onComplete: (AssetBundle bundle) =>
{
//拿到Assetbundle的回调
m_DataTableBundle = bundle;
LoadDataTable();
});
#else
//加载表格
LoadDataTable();
#endif
}
现在已经拿到了Assetbundle,然后从Assetbundle中去加载表格了。