一、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包同步、异步加载,卸载,依赖包
csharp
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 update
void 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 frame
void Update()
{
}
}
3、AB包资源加载管理器
结合单例模式,制作AB包资源加载管理器,方便后续AB包加载使用
csharp
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_IOS
return "IOS";
#elif UNITY_ANDROID
return "Android";
#else
return "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);
else
return 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);
else
return 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);
else
return 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));
else
callBack(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));
else
callBack(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);
else
callBack(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;
}
}
csharp
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;
}
}