1、AB包是什么
特定于平台的资产压缩包,有点类似压缩文件
资产包括:模型、贴图、预设体、音效、材质球等等
2、AB包的作用
相对Resources下的资源AB包更好管理资源
1.减少包体大小:
(1)压缩资源
(2)减少初始包大小
2.热更新
(1)资源热更新
(2)脚本热更新
热更新基本规则:
客户端自带很少的默认资源
资源在资源服务器端,通过对比文件获得最新的各种AB包
3、生成AB包资源文件
1.Unity编辑器开发,自定义打包工具
2.官方提供好的打包工具:Asset Bundle Browser
AssetBundleBrowser参数相关
build(构建页签)
BuildTarget:目标平台
Output Path:目标输出路径
Clear Folders:是否清空文件夹 重新打包
Copy To StreamingAssets:是否拷贝到StreamingAssets
Compression
NoCompression
不压缩,解压快,包较大 不推荐
LZMA
压缩最小,解压慢
缺点:用一个资源 要解压所有
LZ4
压缩,相对LZMA大一点点
建议使用,用什么解压什么,内存占用低
ETI
在资源包中 不包含资源的类型信息
FR
重新打包时需要重新构建包
和ClearFolders不同,它不会删除不再存在的包
ITTC
增量构建检查时,忽略类型数的更改
Append Hash
将文件哈希值附加到资源包名上
SM
严格模式,如果打包时报错了,则打包直接失败无法成功
DRB
运行时构建
AB包生成的文件
AB包文件
资源文件
manifest文件
AB包文件信息
当加载时,提供了关键信息
资源信息,依赖关系,版本信息等等
关键AB包(和目录名一样的包)
主包
AB包依赖关键信息
4、使用AB包资源文件
Unity提供的API
5、AB包资源加载管理器
SingletonAutoMono是一个会自动挂载的继承MonoBehaviour的单例基类
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
}
}
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;
}
}