工具类封装

通过上文中对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
{
/// <summary>
/// 加载AssetBundle工具类 单例
/// </summary>
public class LoadAssetBundleManager: SingletonAutoMono<LoadAssetBundleManager>
{
//主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
}
} /// <summary>
/// 根据名称加载AB包 也会检查相关依赖包 进行加载
/// </summary>
/// <param name="assetBundleName">AB包的名称</param>
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>("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);
}
}
} /// <summary>
/// 从AB包中获取具体资源
/// </summary>
/// <param name="abName">AB包名称</param>
/// <param name="resName">资源名称</param>
/// <returns>Object资源</returns>
public Object LoadResource(string abName, string resName)
{
LoadAssetBundle(abName);
Object resObj = null;
resObj = assetBundlesDic[abName].LoadAsset(resName);
return resObj;
}
/// <summary>
/// 泛型方法重载
/// </summary>
public T LoadResource<T>(string abName, string resName) where T:Object
{
LoadAssetBundle(abName);
T res = assetBundlesDic[abName].LoadAsset<T>(resName);
return res;
}
/// <summary>
/// 根据资源类型重载方法
/// </summary>
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<Object> callback)
{
StartCoroutine(LoadResourceIEn(abName, resName, callback));
}
//异步加载协程
private IEnumerator LoadResourceIEn(string abName, string resName, UnityAction<Object> callback)
{
LoadAssetBundle(abName);
AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync(resName);
yield return request;
callback(request.asset);
}
//根据泛型来异步加资源
public void LoadResourceAsync<T>(string abName, string resName, UnityAction<Object> callback) where T : Object
{
StartCoroutine(LoadResourceIEn<T>(abName, resName, callback));
}
//异步加载协程
private IEnumerator LoadResourceIEn<T>(string abName, string resName, UnityAction<Object> callback) where T :Object
{
LoadAssetBundle(abName);
AssetBundleRequest request = assetBundlesDic[abName].LoadAssetAsync<T>(resName);
yield return request;
callback(request.asset);
}
//根据res类型异步加载资源
//根据泛型来异步加资源
public void LoadResourceAsync(string abName, string resName, System.Type type,UnityAction<Object> callback)
{
StartCoroutine(LoadResourceIEn(abName, resName, type, callback));
}
//异步加载协程
private IEnumerator LoadResourceIEn(string abName, string resName, System.Type type, UnityAction<Object> 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<T>();
}
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<GameObject>("model", "cube");
cube2.transform.position = Vector3.left;
Instantiate(cube2); LoadAssetBundleManager.Instance().LoadResourceAsync<GameObject>("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();

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

  1. Android学习笔记(二)之异步加载图片

    最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出.我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片.开发android应用的朋友可能或多或少碰到加载图片内存 ...

  2. Unity学习笔记(5):动态加载Prefab

    第一种方法,从Resources文件夹读取Prefab Assets/Resources文件夹是Unity中的一个特殊文件夹,在博主当前的认知里,放在这个文件夹里的Prefab可以被代码动态加载 直接 ...

  3. Entity Framework学习笔记(五)----Linq查询(2)---贪婪加载

    请注明转载地址:http://www.cnblogs.com/arhat 在上一章中,我们使用了Linq对Entity Framework进行了一个查询,但是通过学习我们却发现了懒加载给我来的性能上的 ...

  4. ThinkPHP3.2.3学习笔记4---统计ThinkPHP3.2.3加载的文件

    将ThinkPHP3.2.3的入口文件index.php加入一个函数getIncludeFiles,文件内容变成如下所示: <?php // +------------------------- ...

  5. NGUI学习笔记(四):动态加载UI和NGUI事件

    动态加载UI 我们进入一个场景后,如果将这个场景所有可能用到的UI都直接放在场景中做好,由于要在进入场景时就部署好所有的UI对象,那么当UI对象较多时会碰到的问题是:1.初始化场景会产生非常明显的卡顿 ...

  6. 学习笔记 - 用js判断页面是否加载完成实现代码

    用document.onreadystatechange的方法来监听状态改变, 然后用document.readyState == "complete"判断是否加载完成 docum ...

  7. Django 学习笔记(三) --- HTML 模版加载 css、js、img 静态文件

    人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...

  8. selenium学习笔记11——driver.get(url) 页面加载时间太长

    在执行自动化测试用例过程中,发现因为网络慢或其他原因导致driver.get(url) 时,页面一直在加载,页面没有加载完成就不会去继续执行下面的动作,但是实际上需要操作的元素已经加载出来了. 解决方 ...

  9. 吴裕雄--天生自然python学习笔记:python 用pygame模块加载图片

    加载图片 使用几何绘图无法画出精细的图形,所以我们可以把现成的图片加载到 Pygam e 中直接使用 . 加载图片的语法为 : 图片加载后通常会用 convert 方法加以处理, 以增加显示速度,语法 ...

  10. [PyTorch 学习笔记] 7.1 模型保存与加载

    本章代码: https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson7/model_save.py https://githu ...

随机推荐

  1. KingbaseESV8R6延迟提交参数

    前言 队列理论在我们生活中的应用随处可见,例如我们去食堂打饭需要排队,我们生活中随处可见排队的场景. 在计算机领域中,性能诊断等地方使用队列理论的案例也很多.服务器硬件分为动态设备和静态设备.CPU和 ...

  2. KingbaseES Json 系列十一:Json数组操作函数

    KingbaseES Json 系列十一--Json数组操作函数(JSONB_ARRAY_ELEMENTS,JSONB_ARRAY_ELEMENTS_TEXT,JSONB_ARRAY_LENGTH,J ...

  3. 哈希表(HashTable)

    哈希表 哈希表:也叫做散列表.是根据关键字和值(Key-Value)直接进行访问的数据结构.也就是说,它通过关键字 key 和一个映射函数 Hash(key) 计算出对应的值 value,然后把键值对 ...

  4. OpenHarmony嵌套类对象属性变化:@Observed装饰器和@ObjectLink装饰器

    上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型.对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第 ...

  5. Java 学习路线:基础知识、数据类型、条件语句、函数、循环、异常处理、数据结构、面向对象编程、包、文件和 API

    Java 基础 什么是 Java Java 是一种由 Sun Microsystems 于 1995 年首次发布的编程语言和计算平台.Java 是一种通用的.基于类的.面向对象的编程语言,旨在减少实现 ...

  6. Linux 配置Git

    前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 一.用git --version命令检查是否已经安装 二.下载git源码并解压 wget https://github.com/git/ ...

  7. 攻防世界 Mine- IDA静调或x64dbg动调 两种方式

    刷攻防世界的最后一道二星题,记录一下,大佬请飘过 题目 分析过程 我很勇,我先双击看看这是什么 是一个扫雷游戏,第一下运气好没踩雷,发现无法继续输入了:如果运气不好,会输出"您踩雷啦!&qu ...

  8. DS-Net:可落地的动态网络,实际加速1.62倍,快改造起来 | CVPR 2021 Oral

    论文提出能够适配硬件加速的动态网络DS-Net,通过提出的double-headed动态门控来实现动态路由.基于论文提出的高性能网络设计和IEB.SGS训练策略,仅用1/2-1/4的计算量就能达到静态 ...

  9. windows下redis主从配置

    1,复制两个redis文件夹,粘贴在同级目录下 2,分别修改6380和6381文件夹中的redis.window.conf文件 port:分别改为6380.6381 均增加:slaveof 127.0 ...

  10. RC4Drop加密技术:原理、实践与安全性探究

    第一章:介绍 1.1 加密技术的重要性 加密技术在当今信息社会中扮演着至关重要的角色.通过加密,我们可以保护敏感信息的机密性,防止信息被未经授权的用户访问.窃取或篡改.加密技术还可以确保数据在传输过程 ...