Unity___AB包
AB包
一些压缩文件,模型,预制体,图片....
Resources和AB包区别
- Resources打包定死,只读,无法修改
- 存储位置自定义,压缩方式,后期更新
- 减少包体大小
- 热更新
1.资源
2.脚本
热更新过程
- 获取资源地址
- 通过资源对比文件,检测哪些需要热更新,下载
AB包生成的文件
- AB包文件 资源文件
- manifest文件 AB包文件信息,当加载时,提供关键信息,资源信息,依赖关系,版本信息
- 关键AB包和目录名一样
AB Browser 插件相关参数
BuildTarget:目标平台
Output Path:目标输出路径
Clear Folders:是否清空文件夹重新打包
Copy To StreamingAssets:是否拷贝到StreamingAssets
NoCompression
不压缩,解压快,包较大不推荐
LZMA
压缩最小,解压慢
缺点:用一个资源要解压所有
LZ4
压缩,相对LZMA大一点点建议使用,用什么解压什么,内存占用低
Build 参数
ET在资源包中不包含资源的类型信息
FR重新打包时需要重新构建包,和ClearFolders不同,它不会删除不再存在的包
ITTC 增量构建检查时,忽略类型数的更改
Append Hash 将文件哈希值附加到资源包名上
SM 严格模式,如果打包时报错了,则打包直接失败无法成功
DRB 运行时构建
AB包加载资源
//第一步加载AB包
AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" +“mode1");
//第二步加载AB包中的资源
//只是用名字加载会出现同名不同类型资源分不清
//建议大家用泛型加载或者是Type指定类型
Gameobject obj = ab.LoadAsset<Gameobject>( "cube" );
//Gameobject obj = ab.LoadAsset("cube", typeof(Gameobject)) as Game0bject;
Instantiate(obj);
//AB包不能够重复加载否则报错
//AssetBundle ab2 = AssetBundle.LoadFromFile(Application.streamingAssetsPath + " /"+“model");//加载─个圆
GameObject obj2 = ab2.LoadAsset("Sphere" , typeof(GameObject)) as GameObject;
Instantiate(obj);
卸载加载的AB包
//卸载所有加载的AB包,参数为true,加载的资源也会被卸载
AssetBundle.UnloadAllAssetBundles(true);
//也可以自己卸载自己,参数同上
ab.Unload(false);
异步加载:协程
IEnumerator LoadABRes( string ABName,string resName ){
//第一步加载AB包
AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath+"/"+ABName);
yield return abcr;
//第二步加载资源
AssetBundleRequest abq = abcr.assetBundle.LoadAssetAsync(resName,typeof(Sprite));
yield return abq;
//abq.asset as Sprite;
img. sprite = abq.asset as Sprite;
}
依赖问题
一个资源用到别的AB包中的资源,只有把所有需要的依赖包全部加载才能正常使用
通过主包 获取依赖信息
//依赖包的关键知识点利用主包获取依赖信息
//加载主包
AssetBundle abNain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + " /" +"pC");
//加载主包中的固定文件
AssetBundleManifest abManifest = abMain.LoadAsset<AssetBundlewanifest>("AssetBundlewanifest");
//从固定文件中得到依赖信息
string[] strs = abManifest.GetAllDependencies( "model");
//得到了依赖包的名字,并加载需要的依赖
for (int i = 0; i < strs.Length; i++){
AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + strs[i]);
}
打包步骤
- 设置打包对象
- 生成AssetBundle
- 上传服务器
- 下载AssetBundle
- 加载对象
- 使用对象
设置打包对象
设置包名和后缀名
设置打包对象
在Editor目录下创建脚本,方便快速打包
[CustomEditor(typeof(Tools))]
public class Tools : Editor {
public override void OnInspectorGUI() {
base.OnInspectorGUI();
}
//在上方导航栏显示出菜单
[MenuItem("Tools/CreateAssetBundle")]
static void CreateAssetBundle(){
string path ="AB";
//不存在就就建立
if(Directory.Exists(path)==false){
Directory.CreateDirectory(path);
}
// 路径 ,打包方式,平台
BuildPipeline.BuildAssetBundles(path,BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows64);
UnityEngine.Debug.Log("Finished");
}
}
BuildAssetBundleOptions常用参数介绍
UncompressedAssetBundle:不压缩,包体积大
ChunkBasedCompression:创建AssetBundle时使用LZ4压缩。默认情况是Lzma格式,下载AssetBoundle后立即解压。
材质打包
如果不打包预制体的材质,则打包后每个预制体的包都会变大
AB包使用方法
加载AB
- 内存
- 文件
- WWW
- UnityWebRequest
using UnityEngine;
using System.IO;
using System.Collections;
using UnityEngine.Networking;
public class LoadAssetBundle : MonoBehaviour
{
private void Start()
{
StartCoroutine(fromUnityWebRequest());
}
// 1. 内存
IEnumerator fromMemery()
{
string path = @"E:\Study\UnityLearns\Demo-AssetBundle\AB\box.3dobj";
string matpath = @"E:\Study\UnityLearns\Demo-AssetBundle\AB\mat.3dobj";
byte[] Matbytes = File.ReadAllBytes(matpath);
byte[] bytes = File.ReadAllBytes(path);
AssetBundle assetBundle = AssetBundle.LoadFromMemory(bytes);
AssetBundle matAssetBundle = AssetBundle.LoadFromMemory(Matbytes);
GameObject obj = assetBundle.LoadAsset("Cube") as GameObject;
GameObject go = GameObject.Instantiate(obj);
yield return null;
}
// 2. 文件
IEnumerator fromFileOne()
{
string matpath = @"E:\Study\UnityLearns\Demo-AssetBundle\AB\mat.3dobj";
AssetBundle matAssetBundle = AssetBundle.LoadFromFile(matpath);
string path = @"E:\Study\UnityLearns\Demo-AssetBundle\AB\box.3dobj";
AssetBundle ab = AssetBundle.LoadFromFile(path);
GameObject obj = ab.LoadAsset<GameObject>("cube");
Instantiate(obj);
yield return null;
}
IEnumerator fromFileAll()
{
//1.设置所有预制体包名为一样的
string path = @"E:\Study\UnityLearns\Demo-AssetBundle\AB\allobj.u3d";
AssetBundle ab = AssetBundle.LoadFromFile(path);
object[] objs = ab.LoadAllAssets();
foreach (var item in objs)
{
Instantiate((GameObject)item);
}
// Instantiate(obj);
yield return null;
}
// 3. WWW
//1. 无缓存机制
IEnumerator fromWWW1()
{
//1.本地 file:///
string path = @"file:///E:\Study\UnityLearns\Demo-AssetBundle\AB\allobj.u3d";
WWW www = new WWW(path);
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield break;
}
AssetBundle ab = www.assetBundle;
object[] objs = ab.LoadAllAssets();
foreach (var item in objs)
{
Instantiate((GameObject)item);
}
// Instantiate(obj);
yield return null;
}
//2. 有缓存机制
IEnumerator fromWWW2()
{
//1.本地 file:///
string path = @"file:///E:\Study\UnityLearns\Demo-AssetBundle\AB\allobj.u3d";
WWW www = WWW.LoadFromCacheOrDownload(path, 1);//删除这个AB文件夹依然可以从缓存中读取到,如果将版本号改为2,则本地无法读取,但是可以读取AB2文件夹
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield break;
}
AssetBundle ab = www.assetBundle;
object[] objs = ab.LoadAllAssets();
foreach (var item in objs)
{
Instantiate((GameObject)item);
}
// Instantiate(obj);
yield return null;
www.Dispose();
www = null;
}
// 4. UnityWebRequest
IEnumerator fromUnityWebRequest()
{
// string path = @"file:///E:\Study\UnityLearns\Demo-AssetBundle\AB2\box.3dobj";
string path= @"http://localhost:8080/AB/allobj.u3d";
UnityWebRequest unityWebRequest = UnityWebRequestAssetBundle.GetAssetBundle(path);
yield return unityWebRequest.SendWebRequest();
AssetBundle ab = DownloadHandlerAssetBundle.GetContent(unityWebRequest);
// GameObject obj = ab.LoadAsset<GameObject>("cube");
// Instantiate(obj);
object[] objs = ab.LoadAllAssets();
foreach (var item in objs)
{
Instantiate((GameObject)item);
Debug.Log(((GameObject)item).name);
}
yield return null;
}
//加载依赖
IEnumerator fromManifest(){
//略
yield return null;
}
}
上传服务器
我利用的是Tomcat服务器,将AB包放置在webapps文件夹下,通过url:http://localhost:8080/AB/allobj.u3d可以读取到,另外需要在web.xml里面添加配置
<mime-mapping>
<extension>u3d</extension>
<mime-type>application/octet-stream</mime-type>
</mime-mapping>