【Unity】AssetBundle资源异步加载以及AB包卸载

这篇具有很好参考价值的文章主要介绍了【Unity】AssetBundle资源异步加载以及AB包卸载。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

以下代码是基于上一篇文章《AssetBundle资源同步加载》的代码新增了异步加载和AB包卸载功能,有兴趣的同学可以去看看我的上一篇文章。

修改单例模式继承MonoBehaviour

由于异步加载需要配合协程进行功能开发,所以我对之前封装的AB包资源加载管理器进行修改,改为继承MonoBehaviour的单例模式。
主要修改以下内容

public class ABPageManager : MonoBehaviour
{
    private static ABPageManager instance;
    public static ABPageManager Instance
    {
        get
        {
        	//预防忘记把脚本挂上去
            if(instance == null)
            {
            	//如果instance为空,说明脚本没有挂上去,这里new了个GameObject
                GameObject ABPageMgrObj = new GameObject("ABPageMgr");
                //添加管理器脚本
                ABPageMgrObj.AddComponent<ABPageManager>();
                //并设置过场景不移除
                DontDestroyOnLoad(ABPageMgrObj);
            }
            return instance;
        }
    }
    
	private void Awake()
    {
    	//游戏一运行,会先执行Awake函数,这里给instance赋值
        instance = this;
    }
}

异步加载AB包以及依赖包

这里主要用到协程配合AssetBundle提供的异步加载函数进行加载。
AB包异步加载函数:
AssetBundleCreateRequest AssetBundle.LoadFromFileAsync(string path);
这里我写了一个协程专门异步加载AB包

/// <summary>
/// 异步加载AB包
/// </summary>
/// <param name="path">路径</param>
/// <param name="name">包名</param>
/// <param name="isMainPage">是否为主包</param>
/// <returns></returns>
private void LoadABFromFileAsync(string path, string name, bool isMainPage = false)
{
	StartCoroutine(IE_LoadABAsync(path, name, isMainPage));
}

IEnumerator IE_LoadABAsync(string path, string name, bool isMainPage = false)
{
	if (isMainPage)
	{
		AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(path + "/" + name);
		yield return abcr;
		mainPage = abcr.assetBundle;
		abManifest = mainPage.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
	}
	else
	{
		abPageDic.Add(name, null);
		AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(path + "/" + name);
		yield return abcr;
		abPageDic[name] = abcr.assetBundle;
	}
}

需要加载AB包调用LoadABFromFileAsync这个函数开启协程加载即可,比较关键的是,因为异步加载是不能立即得到加载的资源的,所以需要先添加空进字典里面也就是这一句abPageDic.Add(name, null);等加载完成后再进行赋值abPageDic[name] = abcr.assetBundle;。
以下是正儿八经的异步加载主包,依赖包和资源包了

//这个协程函数没有用unity提供的协程调度器来执行
//是自定义了规则执行,所以函数里面yield return了一个string并不是在下一帧就往下执行
	/// <summary>
    /// 异步加载AB包以及主包和其依赖包协程函数
    /// </summary>
    /// <param name="pageName">AB包名</param>
    /// <param name="callback">加载完所有包回调函数</param>
    /// <returns></returns>
    IEnumerator IE_LoadABPage(string pageName, UnityAction callback)
    {
    	//判断主包有没有加载过
        if (mainPage == null && !isAnsycLoadMainPage)
        {
        	//没有加载过的话异步加载主包
            LoadABFromFileAsync(pagePath, MainABPageName, true);
            isAnsycLoadMainPage = true;
            yield return MainABPageName;
        }
        else
        {
        	//加载过主包的话,就直接yield return,检测到加载完后就能继续执行下一步了
            yield return MainABPageName;
        }

        string[] pagesName = abManifest.GetAllDependencies(pageName);//得到所有依赖包的名称
        //加载资源所在的ab包的所有依赖包 因为同一个ab包不能同时加载,所以用一个字典记录加载过的ab包
        for (int i = 0; i < pagesName.Length; i++)
        {
            if (!abPageDic.ContainsKey(pagesName[i]))
            {
                LoadABFromFileAsync(pagePath, pagesName[i]);
                yield return pagesName[i];
            }
            else
                yield return pagesName[i];
        }

        if (!abPageDic.ContainsKey(pageName))
        {
            //加载资源所在的AB包
            LoadABFromFileAsync(pagePath, pageName);
            yield return pageName;
        }
        else
            yield return pageName;

        callback();
    }

这里又写了一个协程函数,因为需要先加载主包,才能得到资源包的依赖信息加载依赖包,异步加载主包不能立刻得到主包的资源,所以就需要协程配合作出分时分步去加载。这个协程函数比较特殊,没用unity提供的协程调度器开启协程,因为我需要yield return 一个AB包名,在Update函数中判断这个包有没有加载完再进行下一步,所以,在开启这个协程的时候,我用了一个List把返回回来的协程对象保存了。

	/// <summary>
    /// 异步加载AB包以及主包和其依赖包
    /// </summary>
    /// <param name="pageName">AB包名</param>
    private void LoadABPageAsync(string pageName, UnityAction callback)
    {
    	//获得IEnumerator对象
        IEnumerator ie = IE_LoadABPage(pageName, callback);
        //执行下一步
        ie.MoveNext();
        //保存IEnumerator对象
        ieList.Add(ie);
    }

因为协程本质上是一个迭代器,我们来看看IEnumerator对象
【Unity】AssetBundle资源异步加载以及AB包卸载
yield return回来的参数可以通过Current得到,MoveNext()可以执行一个协程函数,遇到yield return停止,下一次调用MoveNext()再从上一次停止的yield return语句的下一句开始执行,达到分时分步的效果。MoveNext()返回一个bool值,当返回false时,就说明协程函数执行完了。
回到咱们代码,ie.MoveNext();执行后会遇到yield return MainABPageName;,协程函数会暂时挂起,这里我封装了一个检测AB包加载是否完成的函数,在Update中调用

	/// <summary>
    /// 检测异步加载是否完成,如果完成,IE_LoadABPage协程继续执行
    /// </summary>
    private void DetectionLoadingCompleted()
    {
        for (var i = 0; i < ieList.Count; i++)
        {
            if ((abPageDic.ContainsKey((string)ieList[i].Current) && abPageDic[(string)ieList[i].Current] != null)
                || ((string)ieList[i].Current == MainABPageName && mainPage != null))
            {
                if (!ieList[i].MoveNext())
                {
                    ieList.Remove(ieList[i]);
                }
            }
        }
    }

因为在前面异步加载的时候往字典里面添加了key包名和null值,加载结束后再把加载好的AssetBundle对象赋值到字典中,所以这里判断如果字典中的包名对应的值不为空,就说明加载好了,就可以MoveNext了,当MoveNext返回false,就说明该协程加载好了,就把该协程移出ieList。
在Update中调用这个函数

	private void Update()
    {
        DetectionLoadingCompleted();
    }

加载AB包的逻辑就结束了,AB包加载好了,加载完成后调用传入的callback,就能通知下一步加载AB包中的资源了

异步加载AB包中的资源

重载了三个方法提供给外部使用,三个方法大同小异,和同步加载的三个方法差不多
方法一

//因为异步加载不能实时获得想要的资源,所以需要传入一个UnityAction<Object> callback
	public void LoadABPageResAsync(string pageName, string resName, UnityAction<Object> callback)
    {
    	//先异步加载AB包
        LoadABPageAsync(pageName, () =>
        {
        	//AB包异步加载结束后,开启协程异步加载资源
            StartCoroutine(IE_LoadABPageRes(pageName, resName, callback));
        });
        
    }

    IEnumerator IE_LoadABPageRes(string pageName, string resName, UnityAction<Object> callback)
    {
	    //异步加载资源
        AssetBundleRequest abRequest = abPageDic[pageName].LoadAssetAsync(resName);
        yield return abRequest;
        //资源加载完成后调用callback,把加载好的资源传出去
        callback(abRequest.asset);
    }

方法二

	public void LoadABPageResAsync(string pageName, string resName, System.Type resType, UnityAction<Object> callback)
    {
        LoadABPageAsync(pageName, () =>
        {
            StartCoroutine(IE_LoadABPageRes(pageName, resName, resType, callback));
        });
    }

    IEnumerator IE_LoadABPageRes(string pageName, string resName, System.Type resType, UnityAction<Object> callback)
    {
        AssetBundleRequest abRequest = abPageDic[pageName].LoadAssetAsync(resName, resType);
        yield return abRequest;
        callback(abRequest.asset);
    }

方法三

	public void LoadABPageResAsync<T>(string pageName, string resName, UnityAction<T> callback) where T : Object
    {
        LoadABPageAsync(pageName, () =>
        {
            StartCoroutine(IE_LoadABPageRes<T>(pageName, resName, callback));
        });
    }

    IEnumerator IE_LoadABPageRes<T>(string pageName, string resName, UnityAction<T> callback) where T : Object
    {
        AssetBundleRequest abRequest = abPageDic[pageName].LoadAssetAsync<T>(resName);
        yield return abRequest;
        callback(abRequest.asset as T);
    }

外部使用

	void Start()
    {
        ABPageManager.Instance.LoadABPageResAsync("model", "Cube", (obj) =>
        {
            Instantiate(obj as GameObject).transform.position = new Vector3(0,2,0);
        });

        ABPageManager.Instance.LoadABPageResAsync("model", "Capsule", typeof(GameObject), (obj) =>
        {
            Instantiate(obj as GameObject).transform.position = new Vector3(2, 2, 0);
        });

        ABPageManager.Instance.LoadABPageResAsync<GameObject>("model", "Sphere", (obj) =>
        {
            Instantiate(obj).transform.position = new Vector3(4, 2, 0);
        });
    }

异步加载AB包和AB包中的资源功能就完成了,上面代码有个缺点是,当先异步加载A包的资源a,再同步加载A包的资源b,就会发生AB包重复加载报错的情况,暂时还没想到怎么解决,如有大佬看到麻烦指点一二。

AB包卸载

AB包卸载比较简单,使用AssetBundle提供的卸载函数就行

	/// <summary>
    /// 卸载单个AB包
    /// </summary>
    /// <param name="pageName">AB包名</param>
    public void UnloadABPackage(string pageName)
    {
        if (abPageDic.ContainsKey(pageName))
        {
            abPageDic[pageName].Unload(false);
            abPageDic.Remove(pageName);
        }
    }

    /// <summary>
    /// 卸载所有AB包
    /// </summary>
    public void UnloadAllABPackage()
    {
        AssetBundle.UnloadAllAssetBundles(false);
        abPageDic.Clear();
    }

完整代码

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

public class ABPageManager : MonoBehaviour
{
    private static ABPageManager instance;
    public static ABPageManager Instance
    {
        get
        {
            if(instance == null)
            {
                GameObject ABPageMgrObj = new GameObject("ABPageMgr");
                ABPageMgrObj.AddComponent<ABPageManager>();
                DontDestroyOnLoad(ABPageMgrObj);
            }

            return instance;
        }
    }

    //根据平台自定义主包名,需要和打包的ab包名称相同,用来加载主包
    private string MainABPageName
    {
        get
        {
#if UNITY_IOS
return "IOS";
#elif UNITY_ANDROID
return "ANDROID";
#else
            return "PC";
#endif
        }
    }
    private AssetBundle mainPage;
    private AssetBundleManifest abManifest;

    private string pagePath = Application.streamingAssetsPath;
    private Dictionary<string, AssetBundle> abPageDic = new Dictionary<string, AssetBundle>();
    List<IEnumerator> ieList = new List<IEnumerator>();
    private bool isAnsycLoadMainPage = false;

    private void Awake()
    {
        instance = this;
    }

    private void Update()
    {
        DetectionLoadingCompleted();
    }

    /// <summary>
    /// 同步加载AB包以及主包和其依赖包
    /// </summary>
    /// <param name="pageName">AB包名</param>
    private void LoadABPage(string pageName)
    {
        //加载主包
        if (mainPage == null)
        {
            mainPage = AssetBundle.LoadFromFile(pagePath + "/" + MainABPageName);
            //加载主包中的依赖信息文件,主包中包含了一个记录主包下所有的包的依赖信息,加载此文件可以得到资源所在包的所有依赖包信息
            abManifest = mainPage.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }

        string[] pagesName = abManifest.GetAllDependencies(pageName);//得到所有依赖包的名称
        //加载资源所在的ab包的所有依赖包 因为同一个ab包不能同时加载,所以用一个字典记录加载过的ab包
        for (int i = 0; i < pagesName.Length; i++)
        {
            if (!abPageDic.ContainsKey(pagesName[i]))
            {
                abPageDic.Add(pagesName[i], AssetBundle.LoadFromFile(pagePath + "/" + pagesName[i]));
            }
        }

        if (!abPageDic.ContainsKey(pageName))
        {
            //加载资源所在的AB包
            AssetBundle abPage = AssetBundle.LoadFromFile(pagePath + "/" + pageName);
            abPageDic.Add(pageName, abPage);
        }
    }
    
    

    /// <summary>
    /// 检测异步加载是否完成,如果完成,IE_LoadABPage协程继续执行
    /// </summary>
    private void DetectionLoadingCompleted()
    {
        for (var i = 0; i < ieList.Count; i++)
        {
            if ((abPageDic.ContainsKey((string)ieList[i].Current) && abPageDic[(string)ieList[i].Current] != null)
                || ((string)ieList[i].Current == MainABPageName && mainPage != null))
            {
                if (!ieList[i].MoveNext())
                {
                    ieList.Remove(ieList[i]);
                }
            }
        }
    }

    /// <summary>
    /// 异步加载AB包
    /// </summary>
    /// <param name="path">路径</param>
    /// <param name="name">包名</param>
    /// <param name="isMainPage">是否为主包</param>
    /// <returns></returns>
    private void LoadABFromFileAsync(string path, string name, bool isMainPage = false)
    {
        StartCoroutine(IE_LoadABAsync(path, name, isMainPage));
    }

    IEnumerator IE_LoadABAsync(string path, string name, bool isMainPage = false)
    {
        if (isMainPage)
        {
            AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(path + "/" + name);
            yield return abcr;
            mainPage = abcr.assetBundle;
            abManifest = mainPage.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
        else
        {
            abPageDic.Add(name, null);
            AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(path + "/" + name);
            yield return abcr;
            abPageDic[name] = abcr.assetBundle;
        }
    }

    /// <summary>
    /// 异步加载AB包以及主包和其依赖包
    /// </summary>
    /// <param name="pageName">AB包名</param>
    private void LoadABPageAsync(string pageName, UnityAction callback)
    {
        IEnumerator ie = IE_LoadABPage(pageName, callback);
        ie.MoveNext();
        ieList.Add(ie);
    }

    /// <summary>
    /// 异步加载AB包以及主包和其依赖包协程函数
    /// </summary>
    /// <param name="pageName">AB包名</param>
    /// <param name="callback">加载完所有包回调函数</param>
    /// <returns></returns>
    IEnumerator IE_LoadABPage(string pageName, UnityAction callback)
    {
        if (mainPage == null && !isAnsycLoadMainPage)
        {
            LoadABFromFileAsync(pagePath, MainABPageName, true);
            isAnsycLoadMainPage = true;
            yield return MainABPageName;
        }
        else
        {
            yield return MainABPageName;
        }

        string[] pagesName = abManifest.GetAllDependencies(pageName);//得到所有依赖包的名称
        //加载资源所在的ab包的所有依赖包 因为同一个ab包不能同时加载,所以用一个字典记录加载过的ab包
        for (int i = 0; i < pagesName.Length; i++)
        {
            if (!abPageDic.ContainsKey(pagesName[i]))
            {
                LoadABFromFileAsync(pagePath, pagesName[i]);
                yield return pagesName[i];
            }
            else
                yield return pagesName[i];
        }

        if (!abPageDic.ContainsKey(pageName))
        {
            //加载资源所在的AB包
            LoadABFromFileAsync(pagePath, pageName);
            yield return pageName;
        }
        else
            yield return pageName;

        callback();
    }

    /// <summary>
    /// 同步加载AB包
    /// </summary>
    /// <param name="pageName">AB包名</param>
    /// <param name="resName">资源名</param>
    /// <returns>返回对应的资源对象 Object类型</returns>
    public Object LoadABPageRes(string pageName, string resName)
    {
        LoadABPage(pageName);

        //加载资源并返回
        return abPageDic[pageName].LoadAsset(resName);
    }

    /// <summary>
    /// 同步加载AB包
    /// </summary>
    /// <param name="pageName">AB包名</param>
    /// <param name="resName">资源名</param>
    /// <param name="resType">资源类型</param>
    /// <returns>返回对应的资源对象 Object类型</returns>
    public Object LoadABPageRes(string pageName, string resName, System.Type resType)
    {
        LoadABPage(pageName);
        return abPageDic[pageName].LoadAsset(resName, resType);
    }

    /// <summary>
    /// 同步加载AB包
    /// </summary>
    /// <typeparam name="T">资源类型</typeparam>
    /// <param name="pageName">AB包名</param>
    /// <param name="resName">资源名</param>
    /// <returns>返回对应的资源对象 对应资源的类型</returns>
    public T LoadABPageRes<T>(string pageName, string resName) where T : Object
    {
        LoadABPage(pageName);
        return abPageDic[pageName].LoadAsset<T>(resName);
    }

    public void LoadABPageResAsync(string pageName, string resName, UnityAction<Object> callback)
    {
        LoadABPageAsync(pageName, () =>
        {
            StartCoroutine(IE_LoadABPageRes(pageName, resName, callback));
        });
        
    }

    IEnumerator IE_LoadABPageRes(string pageName, string resName, UnityAction<Object> callback)
    {
        AssetBundleRequest abRequest = abPageDic[pageName].LoadAssetAsync(resName);
        yield return abRequest;
        callback(abRequest.asset);
    }

    public void LoadABPageResAsync(string pageName, string resName, System.Type resType, UnityAction<Object> callback)
    {
        LoadABPageAsync(pageName, () =>
        {
            StartCoroutine(IE_LoadABPageRes(pageName, resName, resType, callback));
        });
    }

    IEnumerator IE_LoadABPageRes(string pageName, string resName, System.Type resType, UnityAction<Object> callback)
    {
        AssetBundleRequest abRequest = abPageDic[pageName].LoadAssetAsync(resName, resType);
        yield return abRequest;
        callback(abRequest.asset);
    }

    public void LoadABPageResAsync<T>(string pageName, string resName, UnityAction<T> callback) where T : Object
    {
        LoadABPageAsync(pageName, () =>
        {
            StartCoroutine(IE_LoadABPageRes<T>(pageName, resName, callback));
        });
    }

    IEnumerator IE_LoadABPageRes<T>(string pageName, string resName, UnityAction<T> callback) where T : Object
    {
        AssetBundleRequest abRequest = abPageDic[pageName].LoadAssetAsync<T>(resName);
        yield return abRequest;
        callback(abRequest.asset as T);
    }

    /// <summary>
    /// 卸载单个AB包
    /// </summary>
    /// <param name="pageName">AB包名</param>
    public void UnloadABPackage(string pageName)
    {
        if (abPageDic.ContainsKey(pageName))
        {
            abPageDic[pageName].Unload(false);
            abPageDic.Remove(pageName);
        }
    }

    /// <summary>
    /// 卸载所有AB包
    /// </summary>
    public void UnloadAllABPackage()
    {
        AssetBundle.UnloadAllAssetBundles(false);
        abPageDic.Clear();
    }
}

本文是学习AB包加载时的记录,如有写的不好地方,欢迎指出,感谢感谢!文章来源地址https://www.toymoban.com/news/detail-402361.html

到了这里,关于【Unity】AssetBundle资源异步加载以及AB包卸载的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Unity 3D】AssetBundle打包、上传、加载、卸载详解及演示(附源码)

    需要源码及依赖请点赞关注收藏后评论区留言私信~~~ AssetBundle最重要的操作就是AssetBundle打包 下载 加载以及卸载 下面就来了解一下AssetBundle的常用操作 AssetBundle打包主要用到下面两个API BuildAssetBundles(string outputPath,AssetBundleBuild[] builds, BuildAssetBundleOptions assetBundleOptions,BuildTarg

    2024年02月10日
    浏览(36)
  • [游戏开发][Unity]Assetbundle下载篇(4)检查断点续传以及开始下载AB包

    打包与资源加载框架目录 下 载 AB包之前,要检查该AB包是否下载中断过,例如用户杀程序,卡死等情况。 前文有讲解过,下载AB包会先下载到临时文件夹,全部下载成功后,全部剪切到persistentDataPath沙盒目录中。 回顾一下之前的筛选机制,哪些AB包可以加入下载列表,其中并

    2024年02月09日
    浏览(47)
  • [游戏开发][Unity]Assetbundle打包与资源加载框架

    我会分三个篇章写整个框架分别是: AB打包篇 AB下载篇 AB加载篇 整个框架内容比较多,属于企业级方案,涉及到增量打包、打包策略、AB包下载、边玩边下、资源管理系统,资源加载系统等功能。 Unity小白看本系列文章可能比较吃力。如果我哪里写的不好,影响理解了,欢迎

    2024年02月13日
    浏览(55)
  • Unity中资源异步加载

            Unity作为一款优秀的游戏引擎,广泛应用于游戏制作领域。在游戏的开发过程中,资源加载的效率和流畅度尤为重要。对于较大的资源文件,同步加载方式可能会导致游戏卡顿、延迟等问题。因此,采用异步加载的方法可以提高游戏的效率和用户体验。 本篇博客将

    2024年02月06日
    浏览(58)
  • Unity学习笔记之AB包(AssetBundle)

    存储在Resources下的资源,最终会存储在游戏的主体包中,发送给用户,手机系统上,如果需要做资源的更新,是无法使用Resources即时更新(不需要关闭手机游戏,即可实现游戏更新). AB包是 独立于游戏主包存在的资源存储文件 ,使用内部资源时,需要单独下载和加载。 AB包

    2024年03月10日
    浏览(44)
  • Unity知识点 -- AssetBundle(AB包)

    特定于平台的资产压缩包,类似于压缩文件 资产包括:模型、贴图、预制体、音效、材质球等 2.1 相对于 Resources 下的资源,AB 包更好管理资源 Resource:打包时定死,只读,无法修改 AB包:存储位置可以自定义,压缩方式可以自定义,后期可以动态更新,通过 AB 包可以做热更

    2024年02月13日
    浏览(44)
  • Unity热更新——AssetBundle(AB包)+管理器

    游戏或者软件更新时,无需重新下周客户端进行安装,而是在应用程序启动的情况下,在内部进行的资源或者代码更新 特定于平台的资产压缩包,有点类似压缩文件,资产包括:模型、贴图、预设体、音效、材质球等等 相对Resources下的资源,AB包更好管理资源,区别是: A

    2024年02月04日
    浏览(37)
  • Unity 性能优化四:UI耗时函数、资源加载、卸载API

    1.1 Canvas.SendWillRenderCanvases 这个函数是由于自身UI的更新,产生的耗时 1. 这里更新的是vertex 属性,比如 color、tangent、position、uv,修改recttransform的position、scale,rotation并不会导致顶点属性改变,因为顶点的position是根据pivot的偏移决定的,而改变其size、pivot、anchor,则会修改

    2024年02月14日
    浏览(50)
  • 2023-06-08 Unity AssetBundle1——AB包介绍与使用

    一、AB 包介绍 ​ AB 包是特定于平台的资源压缩包,类似于压缩文件。其中资源可包括:模型、贴图、预设体、音效、材质球等等。 ​ 相较于 Resources 文件夹下的资源文件,AB 包能够更好管理资源: Resources 文件夹:打包时资源固定,只读,无法修改。 AB 包:存储位置可自定

    2024年02月16日
    浏览(40)
  • [游戏开发][Unity]Assetbundle下载篇(1)热更前准备与下载AB包清单

    打包与资源加载框架目录 热更流程都不是固定的,每个人写的状态机也有所差别,但是一些必要步骤肯定不可能少,例如下载清单,对比版本,下载AB包,标记下载完成。我接下来的每一篇文章都是下载AB包的重要步骤,大概率是不能省略的。 检查沙盒路径是否存在 检查下载

    2024年02月15日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包