码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Unity 热更--AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】


    合集 - Unity学习笔记(19)
    1.Unity学习笔记--基础2023-11-012.Unity学习笔记--入门2023-10-293.Unity学习笔记--数据持久化之PlayerPrefs的使用2023-11-194.Unity学习笔记--数据持久化XML文件(1)2023-11-205.Unity学习笔记--数据持久化XML文件(2)2023-12-016.Unity学习笔记--数据持久化Json2023-12-037.NGUI学习笔记(1)03-018.NGUI学习笔记203-039.NGUI学习笔记3.503-0510.NGUI学习笔记4.003-0611.Unity 热更--AssetBundle学习笔记 0.705-0112.Unity 热更--AssetBundle学习笔记 0.805-02
    13.Unity 热更--AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】05-03
    14.[2]自定义Lua解析方式05-0615.Unity热更学习toLua使用--[1]toLua的导入和默认加载执行lua脚本05-0716.自定义Lua解析器管理器-------演化脚本V0.505-0817.使用自定义委托来调用Lua中的多返回值和长参数类型函数05-0918.使用自定义lua解析管理器调用lua脚本中的table05-1019.Lua热更学习--使用toLua中的协程05-12
    收起

    工具类封装

    通过上文中对AB包加载API的了解和简单使用,对AB包资源加载的几种方法进行封装,将其写入单例类中,如代码展示。

    确保每个AB资源包只加载一次:

    在LoadAssetBundleManager 单例工具类中,首先提供基本的AB包及其AB包依赖包的加载方法,为保持AssetBundle只加载一次,使用DIctionary键值对来记录已经加载出的AB资源。

    主包路径的灵活获取:

    加载主包路径的获取,采用宏来对不同的打包平台来选择对应的主包名称。(可自行定义使用)

    依赖包的加载:

    通过加载主包中的AssetBundleManifest 来获取目标AB包的依赖AB包名称,根据名称进行逐个加载。

    加载方法有异步和同步两种:

    异步加载是在AB包获取之后进行的资源的异步加载,和同步加载一样有对加载函数进行3此重载。分别为根据名称加载,

    泛型加载(C#中使用方便),根据类型加载(供Lua调用)。

    卸载方法的实现:单个AB资源包卸载和所有资源包卸载两种方式。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Events;
    
    namespace BaseFramework
    {
        /// 
        /// 加载AssetBundle工具类 单例 
        /// 
        public class LoadAssetBundleManager: SingletonAutoMono
        {
            //主AB包 
            private AssetBundle mainAssetBundle = null;
            //包体依赖manifest 
            private AssetBundleManifest assetBundleManifest = null;
            
            //防止AB包重复加载 对已经加载的AB包存储
            private Dictionary assetBundlesDic = new Dictionary();
    
            //加载路径
            private string pathAssetBundle
            {
                get
                {
                    return Application.streamingAssetsPath + "/";
                }
            }
            //主包名称
            private string mainAssetBundleName
            {
                get
                {
    #if UnITY_IOS
                    return "IOS";
    #elif UNITY_ANDROID
                    return "Android";
    #else
                    return "StandaloneWindows";
    #endif
                }
            }
    
            /// 
            /// 根据名称加载AB包 也会检查相关依赖包 进行加载
            /// 
            /// AB包的名称
            public void LoadAssetBundle(string assetBundleName)
            {
                if (!assetBundlesDic.ContainsKey(assetBundleName))
                {
                     AssetBundle resAssetBundle = AssetBundle.LoadFromFile(pathAssetBundle+assetBundleName);
                     assetBundlesDic.Add(assetBundleName,resAssetBundle);
                }
                //加载主资源包 从主资源包中获取对manifest
                if (mainAssetBundle == null)
                {
                    mainAssetBundle = AssetBundle.LoadFromFile(pathAssetBundle + mainAssetBundleName);
                    assetBundleManifest = mainAssetBundle.LoadAsset("AssetBundleManifest");
                }
                //加载目标资源包的依赖AB
                string[] dependencies = assetBundleManifest.GetAllDependencies(assetBundleName);
                foreach (var dependency in dependencies)
                {
                    AssetBundle currentAB = null;
                    if (!assetBundlesDic.ContainsKey(dependency))
                    {
                        //加载依赖的ab包
                        currentAB = AssetBundle.LoadFromFile(pathAssetBundle + dependency); 
                        assetBundlesDic.Add(dependency,currentAB);
                    }
                }
            }
    
            /// 
            /// 从AB包中获取具体资源
            /// 
            /// AB包名称
            /// 资源名称
            /// Object资源
            public Object LoadResource(string abName, string resName)
            {
                LoadAssetBundle(abName);
                Object resObj = null;
                resObj = assetBundlesDic[abName].LoadAsset(resName);
                return resObj;
            }
            /// 
            /// 泛型方法重载
            /// 
            public T LoadResource(string abName, string resName) where T:Object
            {
                LoadAssetBundle(abName);
                T res = assetBundlesDic[abName].LoadAsset(resName);
                return res;
            }
            /// 
            /// 根据资源类型重载方法
            /// 
            public Object LoadResource(string abName, string resName, System.Type type)
            {
                LoadAssetBundle(abName);
                Object obj = assetBundlesDic[abName].LoadAsset(resName, type);
                return obj;
            }
            //--------------------------------------------------------
            //同步加载的AB包 异步加载res资源
            public void LoadResourceAsync(string abName, string resName, UnityAction callback)
            {
                StartCoroutine(LoadResourceIEn(abName, resName, callback));
            }
            //异步加载协程
            private IEnumerator LoadResourceIEn(string abName, string resName, UnityAction callback)
            {
                LoadAssetBundle(abName);
                AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync(resName);
                yield return request;
                callback(request.asset);
            }
            //根据泛型来异步加资源
            public void LoadResourceAsync(string abName, string resName, UnityAction callback) where  T : Object
            {
                StartCoroutine(LoadResourceIEn(abName, resName, callback));
            }
            //异步加载协程
            private IEnumerator LoadResourceIEn(string abName, string resName, UnityAction callback) where T :Object
            {
                LoadAssetBundle(abName);
                AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync(resName);
                yield return request;
                callback(request.asset);
            }
            //根据res类型异步加载资源
            //根据泛型来异步加资源
            public void LoadResourceAsync(string abName, string resName, System.Type type,UnityAction callback) 
            {
                StartCoroutine(LoadResourceIEn(abName, resName, type, callback));
            }
            //异步加载协程
            private IEnumerator LoadResourceIEn(string abName, string resName, System.Type type, UnityAction callback) 
            {
                LoadAssetBundle(abName);
                AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync(resName,type);
                yield return request;
                callback(request.asset);
            }
            //资源包的卸载
            public void UnLoadAssetBundle(string abName)
            {
                if (assetBundlesDic.ContainsKey(abName))
                {
                    assetBundlesDic[abName].Unload(false);
                    assetBundlesDic.Remove(abName);
                }
            }
            //卸载所有加载的资源包
            public void UnLoadAllAssetBundle()
            {
                AssetBundle.UnloadAllAssetBundles(false);
                assetBundlesDic.Clear();
                mainAssetBundle = null;
                assetBundleManifest = null;
            }
    
        }
    }
    
    

    该Manager继承的单例脚本:

    using UnityEngine;
    
    namespace BaseFramework
    {
        public class SingletonAutoMono : MonoBehaviour where T : MonoBehaviour
        {
            private static T instance;
    
            public static T Instance()
            {
                if (instance == null)
                {
                    GameObject gameObject = new GameObject();
                    gameObject.name = typeof(T).ToString();
                    DontDestroyOnLoad(gameObject);
                    instance = gameObject.AddComponent();
                }
                return instance;
            }
    
        }
    }
    

    在测试脚本中我们使用6种不同的加载方式进行cube的加载,完成方法测试。

     //测试使用工具类加载
                Object cube = LoadAssetBundleManager.Instance().LoadResource("model", "cube");
                if (cube is GameObject)
                {
                    GameObject cube1 = cube as GameObject;
                    cube1.transform.position = Vector3.up;
                    Instantiate(cube1);
                }
                //异步加载
                LoadAssetBundleManager.Instance().LoadResourceAsync("model", "cube", (obj) =>
                {
                    GameObject cube1 = obj as GameObject;
                    cube1.transform.position = new Vector3(0,1.5f,0);
                    Instantiate(cube1);
                });
                
                //重新测试
                //使用泛型
                GameObject cube2 = LoadAssetBundleManager.Instance().LoadResource("model", "cube");
                cube2.transform.position = Vector3.left;
                Instantiate(cube2);
            
                
                 LoadAssetBundleManager.Instance().LoadResourceAsync("model", "cube", (obj) =>
                 {
                     GameObject cube1 = obj as GameObject;
                     cube1.transform.position = Vector3.right;
                     Instantiate(cube1);
                 });
                 
                 //通过类型加载测试
                 GameObject cube3 = LoadAssetBundleManager.Instance().LoadResource("model", "cube",typeof(GameObject)) as GameObject;
                 cube3.transform.position = new Vector3(0,-1.5f,0);
                 Instantiate(cube3);
    
                 LoadAssetBundleManager.Instance().LoadResourceAsync("model", "cube",typeof(GameObject), (obj) =>
                 {
                     GameObject cube1 = obj as GameObject;
                     cube1.transform.position = Vector3.zero;
                     Instantiate(cube1);
                 });
                 LoadAssetBundleManager.Instance().UnLoadAllAssetBundle();
    

    image-20240502231345546

  • 相关阅读:
    LCD智能婴幼儿秤pcba方案
    [架构之路-232]:目标系统 - 纵向分层 - 操作系统 - 数据存储:文件系统存储方法汇总
    TLS版本及CipherSuites确认及设置
    [FBCTF2019]Event(flask 伪造签名)
    基数排序详解(LSD方法+MSD方法+思路+图解+代码)
    YMK_周报2
    RabbitMQ 利用DelayExchange插件实现延迟队列
    【AGC】云数据库API9开发问题汇总
    Element UI + VUE + datetimerange + el-date-picker + computed 实现开始结束时间联动
    CVE-2015-5254漏洞复现
  • 原文地址:https://www.cnblogs.com/TonyCode/p/18170759
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号