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

news2024/12/30 1:02:33

合集 - 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.coloradmin.cn/o/1644039.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ADS基础教程8-仿真库加载

目录 一、系统库介绍二、厂商库1.模型下载1&#xff09;登录官网2&#xff09;选择所需模型3&#xff09;点击下载4&#xff09;指定保存路径 二.模型加载1&#xff09;设计套件选择2&#xff09;选择解压文件3&#xff09;解压文件成功4&#xff09;添加到当前workspace5&…

在STM32中用寄存器方式点亮流水灯

文章目录 实验资料一、对寄存器的理解1.通俗认识寄存器2.深入了解寄存器&#xff08;1&#xff09;端口配置低寄存器&#xff08;配置0到7引脚的寄存器&#xff09;&#xff08;2&#xff09;端口配置高寄存器&#xff08;配置8到15引脚&#xff09; 3.GPIO口的功能描述 二、配…

在线协作,开源的设计和原型创作平台:penpot

penpot&#xff1a;面向团队&#xff0c;设计自由- 精选真开源&#xff0c;释放新价值。 概览 Penpot 是一款专为跨职能团队量身定制的开源设计软件&#xff0c;与行业领先的 Figma 齐名&#xff0c;提供了一个强大而灵活的在线设计解决方案。其最大的亮点在于&#xff0c;用户…

五一假期零碎时间练习学习过的内容(商城版)

目录 1 总览1.1 技术架构1.2 其他1.2.1 数据库1.2.2 后端部分1.2.2.1 复习feign1.2.2.2 复习下网关网关的核心功能特性&#xff1a;网关路由的流程断言工厂过滤器工厂全局过滤器 过滤器执行顺序解决跨域问题 1.2.2.3 es部分复习 1.2.3 前端部分 2 day1 配置网关2.1 任务2.2 网关…

5.3 调制与解调

信号的调制与解调是通信系统中一对基本的概念&#xff0c;涉及将信息&#xff08;语音、视频、数据等&#xff09;在发送之前进行处理以便在传输介质&#xff08;如无线电波、电话线等&#xff09;上有效传输&#xff0c;以及在接收端恢复这些信息的过程。 一、调制&#xff0…

Java | Leetcode Java题解之第60题排列序列

题目&#xff1a; 题解&#xff1a; class Solution {public String getPermutation(int n, int k) {int[] factorial new int[n];factorial[0] 1;for (int i 1; i < n; i) {factorial[i] factorial[i - 1] * i;}--k;StringBuffer ans new StringBuffer();int[] valid…

虚拟机jvm下

jvm原理与实践 java程序的跨平台特性 jvm基本结构 JVM类加载流程和内存结构总览 类加载 加载阶段 类加载 验证阶段 类加载 准备阶段 类加载 解析阶段 类加载 初始化阶段 程序计数器 虚拟机栈&本地方法栈 栈帧操作 堆 方法区 永久代 元空间 垃圾回收 可触及性

Day12-JavaWeb开发-登录校验(概述/JWT令牌/Fitter/Interceptor)登录认证(会话技术/会话跟踪)

1. 基础登录功能 2. 登录校验-概述 3. 登录认证-登录校验-会话技术 3.1 会话技术 3.2 会话跟踪方案对比 4. 登录校验-JWT令牌 4.1 JWT令牌-介绍 4.2 JWT令牌-生成和校验 4.3 JWT令牌-登录后下发令牌 5. 登录校验-过滤器Fitter 5.1 Fitter-入门 5.2 Fitter-详解(执行流程) 5.3…

Windows php 安装 Memcached扩展、php缺失 Memcached扩展、Class ‘Memcached‘ not found

在Windows系统下如何安装 php Memcached 扩展 下载dll文件 pecl地址&#xff1a;https://pecl.php.net/package/memcached 根据版本进行选择 &#xff1a; 解压下载的文件后得到了这么样的文件结构&#xff1a; 配置 移动dll文件到相应文件位置 重点&#xff1a; libme…

cefsharp实现资源替换如网页背景、移除替换标签、html标识、执行javascript脚本学习笔记(含源码说明)

(一)实现测试(仅供学习参考) 1.1 目标系统页面(登录页)和登录后首页面中2处(一个替换一个移除) 1.2 实现后效果(使用cefsharp自定义浏览器实现以上功能) 1.3 登录后页面替换和移除 系统名称和一个功能菜单li (二)通过分析代码实现脚本编写 2.1 分开处理,设置了…

Swish和H-Swish激活函数:提升模型训练效率

文章目录 Swish激活函数H-Swish激活函数实现总结参考 在深度学习领域&#xff0c;激活函数是神经网络中的关键组成部分&#xff0c;它决定了网络的输出和性能。近年来&#xff0c;研究人员提出了许多新的激活函数&#xff0c;其中Swish激活函数因其独特的性能优势而备受关注。这…

Matlab模拟森林火灾传播

在这个博客中&#xff0c;我们将会介绍一个简单的模拟森林火灾传播的程序&#xff0c;该程序基于一个基本的规则&#xff0c;根据树木状态的不同&#xff0c;以一定的概率生长、燃烧或是灭火&#xff0c;来模拟森林中火灾的传播过程。 目录 一、模拟效果 二、背景介绍 三、模…

Leetcode—1396. 设计地铁系统【中等】

2024每日刷题&#xff08;127&#xff09; Leetcode—1396. 设计地铁系统 实现代码 class UndergroundSystem { public:typedef struct Checkin {string startStation;int time;} Checkin;typedef struct Checkout{int tripNum;int totalTime;} Checkout;UndergroundSystem()…

OneNote导出白色背景文件时将笔记墨迹转换颜色

今天用OneNote导出笔记时发现在文件上做的黑色墨迹笔记全部转成了白色。推测是因为onenote会根据背景色自动转换黑色和白色的墨迹&#xff0c;但是其他颜色好像导出的时候不会转换。 于是&#xff0c;我们首先要转换背景&#xff0c;将黑色背景转成白色背景&#xff0c; 然后将…

buu相册

010分析是一个rar文件&#xff0c;7z打开发现是一个apk文件 但没发现什么敏感信息 全局搜索mail 然后就是查看引用与出处 base解密完是一个邮箱&#xff0c;提交对了。

dynamic_cast 静态转换

dynamic_cast 静态转换 const_cast 常量转换 重新解释转换(reinterpret_cast) 最不安全

用LangChain打造一个可以管理日程的智能助手

众所周知&#xff0c;GPT可以认为是一个离线的软件的&#xff0c;对于一些实时性有要求的功能是完全不行&#xff0c;比如实时信息检索&#xff0c;再比如我们今天要实现个一个日程管理的功能&#xff0c;这个功能你纯依赖于ChatGPT或者其他大语言模型&#xff08;后文简称llm&…

C++ | Leetcode C++题解之第61题旋转链表

题目&#xff1a; 题解&#xff1a; class Solution { public:ListNode* rotateRight(ListNode* head, int k) {if (k 0 || head nullptr || head->next nullptr) {return head;}int n 1;ListNode* iter head;while (iter->next ! nullptr) {iter iter->next;n…

【备战软考(嵌入式系统设计师)】07 - 计算机网络模型

七层模型 计算机网络中比较常见的有OSI七层模型和TCP/IP四层模型。 软考中主要考七层模型&#xff0c;但是实际中使用的还是四层模型比较多&#xff0c;我们主要是为了考试&#xff0c;那就主要讲讲七层模型。不过实际上四层模型就是将七层模型压缩了三层&#xff0c;本质上是…

JVM笔记4-虚拟机类加载机制

1、概述 Java虚拟机把描述类的数据从Class文件加载到内存中&#xff0c;并对数据进行检验、转换解析和初始化&#xff0c;最终形成可以被虚拟机直接使用的Java类型。这个过程称为虚拟机的类加载机制。 2、类加载的时机 一个类型从被加载到内存中开始&#xff0c;到卸载出内存…