如果找不到 Asset Bundle Browser
AB 包官方文档:
如果在 Unity 的 package manager 中没找到 Asset Bundle Browser,可以到他官方文档给出的 git 中下载
我是看的视频:
1. 使用 Asset Bundle Browser 打包
拖动要打包的资源到 Asset Bundle Browser 窗口
然后点击 Build 选项就可以得到打包文件
2. 加载 AB 包
加载场景:
void LoadSceneAB() {
//注意 assetBundleName 和 sceneName 可能不同,一个是 AssetBundle 的名字,一个是 Scene 的名字
string assetBundleName = "keshengsquare.unity3d";
string sceneName = "KeshengSquare";
string path = Application.dataPath + "/StreamingAssets/" + assetBundleName;
var myLoadedAssetBundle = AssetBundle.LoadFromFile(path);
if (myLoadedAssetBundle != null)
{
SceneManager.LoadScene(sceneName);
}
}
加载实例:
void LoadAssetAB() {
//注意 assetBundleName 和 assetName 可能不同,一个是 AssetBundle 的名字,一个是 Asset 的名字
string assetBundleName = "keshengsquare.unity3d";
string assetName = "KeshengSquare";
string path = Application.dataPath + "/StreamingAssets/" + assetBundleName;
var myLoadedAssetBundle = AssetBundle.LoadFromFile(path);
if (myLoadedAssetBundle != null)
{
var assetObj = myLoadedAssetBundle.LoadAsset<GameObject>(assetName);
MonoBehaviour.Instantiate(assetObj);
}
}
3. 设置依赖包
如果两个 AB 包之间有重复的部分,那么就相当于一个资源打包了多次,就会浪费空间
在 Asset Bundle Browser 会自动提示哪些包之间有重复,然后可以右键选择创建依赖包
这个创建依赖包不是说创建出来之后就万事大吉了,他也只是一个 AB 包而已,你原来的两个 AB 包之间的重复的部分被移动到这个新的 AB 包里面了(后面会看到不止是重复的部分)。
但是如果你不加载这个新的 AB 包,也就是说,你原来已经写好了加载两个 AB 包,但之后不写新的代码加载这个新的 AB 包的话,你原来的两个 AB 包就会丢失掉那些被移动到新 AB 包的内容。
所以还需要一个代码来加载依赖包
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Load : MonoBehaviour
{//处理依赖关系的加载,必须加载主AB包,因为依赖关系都存储在主AB包中
void Start()
{
//加载主AB包(不是ab文件夹,是ab文件!)
AssetBundle main = AssetBundle.LoadFromFile("主AB包‘路径’(无后缀名)");
//获取AB包的配置文件
AssetBundleManifest manifest = main.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
//分析预制体所在AB包,依赖哪些AB包
string [] deps= manifest.GetAllDependencies("预制体AB包‘名’(无后缀名)");
//加载依赖的AB包
for(int i=0;i<deps.Length;i++)
{
AssetBundle.LoadFromFile("存放所有文件夹的路径/" + deps[i]);
}
//加载预制体所在的AB包
AssetBundle imageab= AssetBundle.LoadFromFile("预制体AB包路径(无后缀名)");
//加载预制体(内部资源)
GameObject prefab = imageab.LoadAsset<GameObject>("预制体名字");
//附:
//实例化
GameObject gob = Instantiate(prefab);
//设置父物体
gob.transform.SetParent(GameObject.Find("/Canvas").transform);
}
}
4. 依赖包的优化
依赖包会包括重复的两个包中,所有可能重复的部分
比如依赖包是这样子的,由于角色用到了若干个动画,而一个动画对应一个动作模型,也就是有多个模型
但是实际上角色只用到了一个模型
优化方法就是
-
角色动画不包含模型
这个要在动画制作的时候就调好,需要动画制作注意
-
在打包之前,就在 Unity 中,把每个动画对应的多余的动作模型删除,只留下动画片段
-
从根本上让两个 AB 包之间没有重复
比如一开始是打包场景和角色,场景中含有角色,所以两个包有重复,那现在在 Unity 场景中先删去角色,然后再打包,场景和角色的 AB 包就没有重复了,然后在游戏过程中动态添加角色
5. 分包设计
如果有很多角色,是把所有角色都放到一个 AB 包里面,做替换更新,还是将不同角色放到不同 AB 包里面,做增量更新?
显然是后者比较好
同时在加密的过程中,每次加密解密也需要耗时,大的 AB 包解密更耗时
6. 资源加载框架
6.1 防止多次加载 AB 包
//AB包缓存---解决AB包无法重复加载的问题 也有利于提高效率。
private Dictionary<string, AssetBundle> abCache;
...
//加载AB包
private AssetBundle LoadABPackage(string abName)
{
AssetBundle ab;
//加载ab包,需一并加载其依赖包。
if (mainAB == null)
{
//根据各个平台下的基础路径和主包名加载主包
mainAB = AssetBundle.LoadFromFile(basePath + mainABName);
//获取主包下的AssetBundleManifest资源文件(存有依赖信息)
mainManifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
}
//根据manifest获取所有依赖包的名称 固定API
string[] dependencies = mainManifest.GetAllDependencies(abName);
//循环加载所有依赖包
for (int i = 0; i < dependencies.Length; i++)
{
//如果不在缓存则加入
if (!abCache.ContainsKey(dependencies[i]))
{
//根据依赖包名称进行加载
ab = AssetBundle.LoadFromFile(basePath + dependencies[i]);
//注意添加进缓存 防止重复加载AB包
abCache.Add(dependencies[i], ab);
}
}
//加载目标包 -- 同理注意缓存问题
if (abCache.ContainsKey(abName)) return abCache[abName];
else
{
ab = AssetBundle.LoadFromFile(basePath + abName);
abCache.Add(abName, ab);
return ab;
}
}
6.2 区分编辑器模式和打包模式
编辑器模式下不使用 AB 包加载资源,这样就可以快速测试,不需要我每次新增一个资源都要打包,可以等到我测试好了,修改好了之后,再切换到打包模式,打包模式下资源的加载使用 AB 包