[游戏开发][Unity]Assetbundle加载篇(7)AssetBundle加载任务详解

目录

打包与资源加载框架目录

正文

关于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);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Little丶Seven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值