目录
正文
关于AB包的基础文章这里就不介绍了,怎么打AB包前文打包篇已讲,
AB包怎么用?
第一步是加载AB包
异步加载
public void StartLoadBundle(string path)
{
_bundleRequest = AssetBundle.LoadFromFileAsync(path);
_bundleRequest.completed += LoadBundleComplete;
}
private void LoadBundleComplete(AsyncOperation op)
{
if (op.isDone)
{
_bundle = _bundleRequest.assetBundle;
}
}
同步加载
_bundle = AssetBundle.LoadFromFile(path);
拿到bundle包后,第二步是从AB包里加载资源,加载API也由同步和异步
异步接口
_assetRequest = _bundle.LoadAssetAsync(_assetName, _targetType);
_assetRequest.completed += LoadAssetCallback;
private void LoadAssetCallback(AsyncOperation op)
{
if (op.isDone)
{
_target = _assetRequest.asset;
}
}
同步加载API
_target = _bundle.LoadAsset(_assetName, _targetType);
加载ab包以及加载ab包内资源的方式介绍完了,资源加载完了,自然是要通知Loader加载结果,和EditorLoadTask一样。
if (_target != null)
_loadState = TaskLoadState.LoadAssetSuccess;
else
_loadState = TaskLoadState.LoadAssetFailed;
_callback?.Invoke(_target, _target != null);
下面还是以加载UIConfig.bytes打包后的uiconfig.unity3d包为例,因为我们资源打包的思路是,路径不变,但路径名全部变小写。
AssetBundle加载需要注意以下几点
1、ab包如果没依赖包,那么直接按资源路径加载就好了,如果有依赖,调用加载资源API之前必须把ab包和依赖以及依赖的依赖全部加载完成。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ABLoadTask:LoadTaskBase
{
//AB的所有依赖
private List<ABLoadTask> _depends = new List<ABLoadTask>(10);
//
public string _bundleLoadPath;
//
private AssetBundleCreateRequest _bundleRequest;
//
private AssetBundleRequest _assetRequest;
private AssetBundle _bundle;
//引用次数
private int RefCount;
//资源名
protected string _assetName;
public override void DoTask()
{
int lastPoint = _loadResPath.LastIndexOf(".");
int lastXieGang = _loadResPath.LastIndexOf("/");
string extension = _loadResPath.Substring(lastPoint);
//无扩展的路径
string notExtPath = _loadResPath.Substring(0, lastPoint);
//保存文件名,带类型
_assetName = _loadResPath.Substring(lastXieGang + 1, lastPoint - lastXieGang - 1) + extension;
//小写路径
_bundleLoadPath = "assets/works/res/" + notExtPath.ToLower() + ".unity3d";
StartLoadBundle(Application.streamingAssetsPath + "/" + _bundleLoadPath);
}
public void StartLoadBundle(string path)
{
if (GameSetting.Instance.LoadBundleAsync)
{
LogManager.LogProcedure("StartLoadBundle Async:" + path);
_bundleRequest = AssetBundle.LoadFromFileAsync(path);
_bundleRequest.completed += LoadBundleComplete;
_loadState = TaskLoadState.LoadingBundle;
}
else
{
LogManager.LogProcedure("StartLoadBundle:" + path);
_bundle = AssetBundle.LoadFromFile(path);
_loadState = TaskLoadState.LoadBundleSuccess;
}
SetDependencies();
}
private void LoadBundleComplete(AsyncOperation op)
{
if (op.isDone)
{
if (_loadState == TaskLoadState.UnLoadBundle)
{
_bundleRequest.assetBundle.Unload(false);
return;
}
//LogManager.LogInfo("LoadBundleComplete,path:" + _bundleLoadPath);
_bundle = _bundleRequest.assetBundle;
_loadState = TaskLoadState.LoadBundleSuccess;
}
}
//设置依赖Loader
public void SetDependencies()
{
string[] allDepends = AssetBundleManager.Instance.GetBundleDepends(_bundleLoadPath);
for (int i = 0; i < allDepends.Length; i++)
{
//LogManager.LogProcedure($"_bundleLoadPath:{_bundleLoadPath} 存在依赖: {allDepends[i]}");
//创建依赖并添加依赖
ABLoadTask task = LoadTaskManager.Instance.GetABLoadTask(allDepends[i], out bool hasBundle, true);
task._depends.Add(task);
task._bundleLoadPath = allDepends[i];
if (hasBundle == false)
task.StartLoadBundle(Application.streamingAssetsPath + "/" + allDepends[i]);
}
}
//递归检查依赖包是否全部完成
public bool IsDone()
{
if (_depends.Count == 0)//无依赖证明是最底层的Bundle
return _loadState == TaskLoadState.LoadBundleSuccess;
else
{
//检查本包的所有依赖,只要有一个未完成,则直接返回未完成
for (int i = 0; i < _depends.Count; i++)
{
if (_depends[i].IsDone() == false)
{
return false;
}
return true;
}
}
return false;
}
/// <summary>
/// 引用(引用计数递加)
/// </summary>
public virtual void Reference()
{
RefCount++;
}
/// <summary>
/// 释放(引用计数递减)
/// </summary>
public virtual void DeReference()
{
RefCount--;
}
//卸载此包,递归删除引用
public void UnLoadBundle()
{
for (int i = 0; i < _depends.Count; i++)
{
_depends[i].DeReference();
_depends[i].UnLoadBundle();
}
if (RefCount <= 0)
{
_loadState = TaskLoadState.UnLoadBundle;
_bundleRequest.assetBundle.Unload(false);
}
}
public override void Tick()
{
//_assetName不空表示是主包,非依赖包
if (_loadState == TaskLoadState.LoadBundleSuccess && !string.IsNullOrEmpty(_assetName))
{
if (IsDone() == true)//所有依赖全部加载完成
{
//Debug.LogError("AB包及依赖加载完成:" + _loadResPath);
if (_targetType == typeof(Scene))
{
_loadState = TaskLoadState.LoadAssetSuccess;
_callback?.Invoke(null, true);
}
else
{
_loadState = TaskLoadState.LoadingAsset;
if (GameSetting.Instance.LoadAssetAsync)
{
if (_targetType == null)
_assetRequest = _bundle.LoadAssetAsync(_assetName);
else
_assetRequest = _bundle.LoadAssetAsync(_assetName, _targetType);
_assetRequest.completed += LoadAssetCallback;
}
else
{
if (_targetType == null)
_target = _bundle.LoadAsset(_assetName);
else
_target = _bundle.LoadAsset(_assetName, _targetType);
CheckAsset();
}
}
}
}
}
/// <summary>
/// 所有依赖包加载完成后,加载Asset资源
/// </summary>
/// <param name="op"></param>
private void LoadAssetCallback(AsyncOperation op)
{
if (op.isDone)
{
//LogManager.LogProcedure("LoadAssetCallback,assetName:" + _assetName);
_target = _assetRequest.asset;
CheckAsset();
}
}
private void CheckAsset()
{
if (_target != null)
_loadState = TaskLoadState.LoadAssetSuccess;
else
_loadState = TaskLoadState.LoadAssetFailed;
// 通知Loader加载结果
_callback?.Invoke(_target, _target != null);
}
}