【Unity开发】热更新学习——AssetBundle
一、AB包介绍
1、是什么
2、作用
(1)相对于Resources下的资源,AB包更好管理资源
(2)减小包体大小
能够压缩资源,减少初始包大小
(3)可以进行热更新
热更新可以分为:资源热更新和脚本热更新
热更新基本规则:
二、AB包使用
1、生成AB包
(1)Unity编辑器开发,自定义打包工具
(2)官方提供的打包工具:AssetBundleBrowser
(i)安装
可以直接去github下载,然后进行导入
(ii)打包流程
(iii)打包重要参数设置界面
(iv)AB包内容预览窗口
(v)AB包生成的文件
2、使用AB包
(1)AB包同步、异步加载,卸载,依赖包
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class ABTest : MonoBehaviour
{public Image image;// Start is called before the first frame updatevoid Start(){//一、同步加载//1.加载AB包AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "model");//2.加载AB包中指定的模型//加载方式一GameObject gameObject = ab.LoadAsset<GameObject>("Cube");//加载方式二GameObject gameObject1 = ab.LoadAsset("Cube", typeof(GameObject)) as GameObject;//3.创建该模型Instantiate(gameObject);Instantiate(gameObject1);//二、异步加载->协程//StartCoroutine(LoadAB("picture", "4"));//三、卸载AB包//1.卸载所有加载的AB包,false不会卸载AB中包含的资源,true会,一般保持为false//AssetBundle.UnloadAllAssetBundles(false);//2.卸载单个加载的AB包,false不会卸载AB中包含的资源,true会,一般保持为false//ab.Unload(false);//四、关于AB包的依赖—一个资源身上用到了别的AB包中的资源//这个时候如果只加载自己的AB包,通过它创建对象,会出现资源丢失的情况//这时候需要把依赖包一起加载了,才能正常//1.当依赖包比较少,可以直接加载依赖包//AssetBundle ab1 = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "picture");//2.当依赖包过多时,可以通过主包获取依赖信息,从而进行依赖包的加载//加载主包AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "StandaloneWindows");//加载主包中的固定文件AssetBundleManifest abMainifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest");//从固定文件中获取依赖包名string[] name = abMainifest.GetAllDependencies("model");//打印依赖的包名,并加载依赖包for (int i = 0; i < name.Length; i++){print(name[i]);AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + name[i]);}//注意点//1.AB包只能加载一次,重复加载会报错}IEnumerator LoadAB(string abName,string resName){AssetBundleCreateRequest abcr=AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + abName);yield return abcr;AssetBundleRequest abr = abcr.assetBundle.LoadAssetAsync(resName, typeof(Sprite));yield return abr;image.sprite = abr.asset as Sprite;}// Update is called once per framevoid Update(){}
}
3、AB包资源加载管理器
结合单例模式,制作AB包资源加载管理器,方便后续AB包加载使用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// 知识点
/// 1.AB包相关的API
/// 2.单例模式
/// 3.委托——>Lambda表达式
/// 4.协程
/// 5.字典
/// </summary>
public class ABMgr : SingletonAutoMono<ABMgr>
{//AB包管理器 目的是//让外部更方便的进行资源加载//主包private AssetBundle mainAB = null;//依赖包获取用的配置文件private AssetBundleManifest manifest = null;//AB包不能够重复加载 重复加载会报错//字典 用字典来存储 加载过的AB包 private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();/// <summary>/// 这个AB包存放路径 方便修改/// </summary>private string PathUrl{get{return Application.streamingAssetsPath + "/";}}/// <summary>/// 主包名 方便修改/// </summary>private string MainABName{get{
#if UNITY_IOSreturn "IOS";
#elif UNITY_ANDROIDreturn "Android";
#elsereturn "PC";
#endif}}/// <summary>/// 加载AB包/// </summary>/// <param name="abName"></param>public void LoadAB( string abName ){//加载AB包if (mainAB == null){mainAB = AssetBundle.LoadFromFile(PathUrl + MainABName);manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");}//我们获取依赖包相关信息AssetBundle ab = null;string[] strs = manifest.GetAllDependencies(abName);for (int i = 0; i < strs.Length; i++){//判断包是否加载过if (!abDic.ContainsKey(strs[i])){ab = AssetBundle.LoadFromFile(PathUrl + strs[i]);abDic.Add(strs[i], ab);}}//加载资源来源包//如果没有加载过 再加载if (!abDic.ContainsKey(abName)){ab = AssetBundle.LoadFromFile(PathUrl + abName);abDic.Add(abName, ab);}}//同步加载 不指定类型public Object LoadRes(string abName, string resName){//加载AB包LoadAB(abName);//为了外面方便 在加载资源时 判断一下 资源是不是GameObject//如果是 直接实例化了 再返回给外部Object obj = abDic[abName].LoadAsset(resName);if (obj is GameObject)return Instantiate(obj);elsereturn obj;}//同步加载 根据type指定类型public Object LoadRes(string abName, string resName, System.Type type){//加载AB包LoadAB(abName);//为了外面方便 在加载资源时 判断一下 资源是不是GameObject//如果是 直接实例化了 再返回给外部Object obj = abDic[abName].LoadAsset(resName, type);if (obj is GameObject)return Instantiate(obj);elsereturn obj;}//同步加载 根据泛型指定类型public T LoadRes<T>(string abName, string resName) where T:Object{//加载AB包LoadAB(abName);//为了外面方便 在加载资源时 判断一下 资源是不是GameObject//如果是 直接实例化了 再返回给外部T obj = abDic[abName].LoadAsset<T>(resName);if (obj is GameObject)return Instantiate(obj);elsereturn obj;}//异步加载的方法//这里的异步加载 AB包并没有使用异步加载//知识从AB包中 加载资源时 使用异步//根据名字异步加载资源public void LoadResAsync(string abName, string resName, UnityAction<Object> callBack){StartCoroutine(ReallyLoadResAsync(abName, resName, callBack));}private IEnumerator ReallyLoadResAsync(string abName, string resName, UnityAction<Object> callBack){//加载AB包LoadAB(abName);//为了外面方便 在加载资源时 判断一下 资源是不是GameObject//如果是 直接实例化了 再返回给外部AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);yield return abr;//异步加载结束后 通过委托 传递给外部 外部来使用if (abr.asset is GameObject)callBack(Instantiate(abr.asset));elsecallBack(abr.asset);}//根据Type异步加载资源public void LoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack){StartCoroutine(ReallyLoadResAsync(abName, resName, type, callBack));}private IEnumerator ReallyLoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack){//加载AB包LoadAB(abName);//为了外面方便 在加载资源时 判断一下 资源是不是GameObject//如果是 直接实例化了 再返回给外部AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName, type);yield return abr;//异步加载结束后 通过委托 传递给外部 外部来使用if (abr.asset is GameObject)callBack(Instantiate(abr.asset));elsecallBack(abr.asset);}//根据泛型 异步加载资源public void LoadResAsync<T>(string abName, string resName, UnityAction<T> callBack) where T:Object{StartCoroutine(ReallyLoadResAsync<T>(abName, resName, callBack));}private IEnumerator ReallyLoadResAsync<T>(string abName, string resName, UnityAction<T> callBack) where T : Object{//加载AB包LoadAB(abName);//为了外面方便 在加载资源时 判断一下 资源是不是GameObject//如果是 直接实例化了 再返回给外部AssetBundleRequest abr = abDic[abName].LoadAssetAsync<T>(resName);yield return abr;//异步加载结束后 通过委托 传递给外部 外部来使用if (abr.asset is GameObject)callBack(Instantiate(abr.asset) as T);elsecallBack(abr.asset as T);}//单个包卸载public void UnLoad(string abName){if( abDic.ContainsKey(abName) ){abDic[abName].Unload(false);abDic.Remove(abName);}}//所有包的卸载public void ClearAB(){AssetBundle.UnloadAllAssetBundles(false);abDic.Clear();mainAB = null;manifest = null;}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;//C#中 泛型知识点
//设计模式 单例模式的知识点
//继承这种自动创建的 单例模式基类 不需要我们手动去拖 或者 api去加了
//想用他 直接 GetInstance就行了
public class SingletonAutoMono<T> : MonoBehaviour where T : MonoBehaviour
{private static T instance;public static T GetInstance(){if( instance == null ){GameObject obj = new GameObject();//设置对象的名字为脚本名obj.name = typeof(T).ToString();//让这个单例模式对象 过场景 不移除//因为 单例模式对象 往往 是存在整个程序生命周期中的DontDestroyOnLoad(obj);instance = obj.AddComponent<T>();}return instance;}}