Unity 热更--AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】

devtools/2024/11/15 0:50:46/

合集 - Unity学习笔记(13)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-03:西部世界move加速器7.NGUI学习笔记(1)03-018.NGUI学习笔记203-039.NGUI学习笔记3.503-0510.NGUI学习笔记4.003-0611.Unity 热更–AssetBundle学习笔记 0.705-0112.Unity 热更–AssetBundle学习笔记 0.805-0213.Unity 热更–AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】05-03收起

工具类封装

通过上文中对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<string, AssetBundle> assetBundlesDic = new Dictionary<string, AssetBundle>(); |
|  |  |
|  | //加载路径 |
|  |  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<T> : 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


http://www.ppmy.cn/devtools/34289.html

相关文章

交互中的“互”难以产生的原因

脑机交互技术的目标是通过分析和解读大脑活动&#xff0c;将其与特定的意图、指令或行为连接起来。通过训练和分析&#xff0c;可以建立起大脑活动与特定行为或意图之间的关联模型&#xff0c;从而实现脑机交互的应用&#xff0c;例如控制外部设备、传递信息等。然而&#xff0…

关系型数据库MySql分库分表带来的问题以及解决方案

水平分表 水平分表是什么&#xff1f; 将一张表横向拆分为多张表&#xff0c;拆分的表&#xff0c;依然在同一个库中。 例如&#xff0c;user表有400w条记录&#xff0c;将user表拆分成4张表&#xff0c;每张表100w条记录。拆分后的表名&#xff0c;分别叫做user_0、user1、u…

C++:map和set类

关联式容器 在初阶阶段&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector、list、deque、 forward_list(C11)等&#xff0c;这些容器统称为序列式容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;里面 存储的是元素本身。那什么是关…

OpenCV如何使用 GDAL 读取地理空间栅格文件(72)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV的周期性噪声去除滤波器(70) 下一篇 &#xff1a;OpenCV 库来捕获和处理视频输入和相似度测量(73) 目录 目标 代码&#xff1a; 解释&#xff1a; 如何使用 GDAL 读取栅格数据 注意 通…

在Ubuntu 24.04 LTS (Noble Numbat)上搭建Kubernetes集群

准备工作 系统准备 主机和IP地址准备 ​编辑安装步骤 安装前准备 关闭防火墙 设置服务器时区 关闭 swap 分区 关闭SELinux 配置hosts配置文件 转发 IPv4 并让 iptables 看到桥接流量 每台机器设置hostname 安装容器运行时 安装Kubernetes 配置并安装apt包 初始…

Django关于ORM的增删改查

Django中使用orm进行数据库的管理&#xff0c;主要包括以下步骤 1、创建model&#xff0c; 2、进行迁移 3、在视图函数中使用 以下的内容可以先从查询开始看&#xff0c;这样更容易理解后面删除部分代码 主要包括几下几种&#xff1a; 1、增 1&#xff09;实例例化model,代…

【C++之map的应用】

C学习笔记---021 C之map的应用1、map的简单介绍1.1、基本概念1.2、map基本特性 2、map的基本操作2.1、插入元素2.2、访问元素2.3、删除元素2.4、遍历map2.5、检查元素是否存在2.6、获取map的大小2.7、清空map2.8、基本样例 3、map的基础模拟实现4、测试用例4.1、插入和遍历4.2、…

JAVA------基础篇

java基础 1.JDK JDK :java development kit JRE&#xff1a;java runtime environment JDK包含JRE java跨平台&#xff1a;因为java程序运行依赖虚拟机&#xff0c;虚拟机需要有对应操作系统的版本&#xff0c;而jre中有虚拟机。 当你想要在Linux系统下运行&#xff0c;则需要…