[游戏开发][Unity]Assetbundle加载篇(5)加载任务相关代码

 目录

打包与资源加载框架目录

正文

上一篇文章降到了开启加载任务,本篇文章先展示加载任务相关的所有代码

加载任务有3部分代码,

  1. LoadTaskManager维护所有加载任务
  2. 编辑器模式EditorLoadTask
  3. AssetBundle模式ABLoadTask

 LoadTaskManager:

using System;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using System.Linq;
#endif
using UnityEngine;

public class LoadTaskManager:Singleton<LoadTaskManager>
{
#if UNITY_EDITOR
    public Dictionary<string, EditorLoadTask> _allEditorLoadTask = new Dictionary<string, EditorLoadTask>();
#endif
    public Dictionary<string, ABLoadTask> _allABLoadTask = new Dictionary<string, ABLoadTask>();
    /// <summary>
    /// 初始化接口
    /// </summary>
    /// <param name="root"></param>
	public void Init()
    {
    }

    public void CreateLoadTask(AssetLoaderBase loader, Action<UnityEngine.Object, bool> callback,Type t)
    {
        //只有编辑器才要考虑是否用AB
#if UNITY_EDITOR
        //GameSetting.Instance == null说明配置文件还没加载
        if (GameSetting.Instance == null || !GameSetting.Instance.AssetbundleMode)//不用AB,直接加载
        {
            EditorLoadTask task = new EditorLoadTask();
            _allEditorLoadTask.Add(loader._resPath, task);
            task.StartTask(loader._resPath, callback, t);
            return;
        }
#endif
        {
            //Editor模拟AB和正常的AB加载走这里
            ABLoadTask task = GetABLoadTask(loader._resPath, out bool hasBundle);
            if (hasBundle == false)
                task.StartTask(loader._resPath, callback, t);
        }
      
    }

    public ABLoadTask GetABLoadTask(string loadPath, out bool hasBundle, bool isDepend = false)
    {
        ABLoadTask task;
        if (_allABLoadTask.TryGetValue(loadPath, out task))
        {
            //Debug.Log("GetABLoadTask,已存在path: " + loadPath);
            if (isDepend)
                task.Reference();
            hasBundle = true;
        }
        else
        {
            //Debug.Log("GetABLoadTask,不存在,创建 path: " + loadPath);
            task = new ABLoadTask();
            task._bundleLoadPath = loadPath;
            _allABLoadTask.Add(loadPath, task);
            hasBundle = false;
        }
        return task;
    }

    public void Tick(float deltaTime)
    {
#if UNITY_EDITOR
        for (int i = 0; i < _allEditorLoadTask.Count; i++)
        {
            var item = _allEditorLoadTask.ElementAt(i);
            item.Value.Tick();
        }
#endif

        foreach (var task in _allABLoadTask)
        {
            task.Value.Tick();
        }
    }

    public void UnLoadNoUseBundle()
    { 
        
    }
}

 ABLoadTask

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

 EditorLoadTask

#if UNITY_EDITOR

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;

public class EditorLoadTask:LoadTaskBase
{
    /*
     * 使用方式:
     * "Works/Res/Prefabs/UIPanel/Canvas.prefab"
     * 要带着文件扩展名
     */
    public override void DoTask()
    {
        string path = "Assets/Works/Res/" + _loadResPath;

        if (_targetType != typeof(Scene))
            _target = AssetDatabase.LoadAssetAtPath(path, _targetType);
        //模拟异步下一帧加载
        _loadState = TaskLoadState.LoadingAsset;
    }

    public override void Tick()
    {
        if (_loadState != TaskLoadState.LoadingAsset)
            return;
        if (_targetType == typeof(Scene))
        {
            LoadSceneParameters parameters = new LoadSceneParameters() { loadSceneMode = LoadSceneMode.Single, localPhysicsMode = LocalPhysicsMode.None };
            AsyncOperation asyncOperation = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode("Assets/" + _loadResPath, parameters);
            //Scene scene = UnityEditor.SceneManagement.EditorSceneManager.GetSceneByPath("Assets/" + _loadResPath, parameters);
            Scene scene = UnityEditor.SceneManagement.EditorSceneManager.GetSceneByPath("Assets/" + _loadResPath);
            if (scene == null) {
                _loadState = TaskLoadState.LoadAssetFailed;
                //通知ResourceLoader加载成功或失败
                _callback?.Invoke(null, false);
            }
            else
            {
                _loadState = TaskLoadState.LoadAssetSuccess;
                //通知ResourceLoader加载成功或失败
                _callback?.Invoke(null, true);
            }

        }
        else
        {
            _loadState = _target == null ? TaskLoadState.LoadAssetFailed : TaskLoadState.LoadAssetSuccess;
            if (_loadState == TaskLoadState.LoadAssetFailed)
                LogManager.LogError($"Failed to load asset object : path:{_loadResPath}, type:{_targetType.ToString()}");
            通知Loader加载结果
            _callback?.Invoke(_target, _target != null);
        }
    }
}
#endif

LoadTaskBase 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum TaskLoadState
{
    None = 0,
    LoadingBundle = 1,
    LoadBundleSuccess = 2,
    LoadingAsset = 3,//LoadingAsset状态 //AB模式代表AB及依赖已全部加载完成,Editor模式下一帧加载
    LoadAssetSuccess = 4,
    LoadAssetFailed = 5,
    UnLoadBundle = 6,
}

public abstract class LoadTaskBase
{
    protected string _loadResPath;

    protected TaskLoadState _loadState;

    protected Action<UnityEngine.Object, bool> _callback;

    protected Type _targetType;
    //目标类型
    protected UnityEngine.Object _target;

    public void StartTask(string loadResPath,Action<UnityEngine.Object, bool> callback,Type t)
    {

        _loadResPath = loadResPath;
        _targetType = t;
        _loadState = TaskLoadState.LoadingBundle;
        _callback = callback;
        DoTask();
    }

    /// <summary>
    /// 交给子类去完成任务
    /// </summary>
    public abstract void DoTask();
    public abstract void Tick();
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Little丶Seven

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

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

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

打赏作者

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

抵扣说明:

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

余额充值