打包AssetBundle文件
一、什么是AssetBundle
基本可以给为两点:
1. 它是一个存在于硬盘上的文件。可以称之为压缩包。这个压缩包可以认为是一个文件夹,里面包含了多个文件。这些文件可以认为两类:Serialized File和Resources File。
Serialized File (序列化文件):资源被打碎放在一个对象中,最后统一被写进一个单独的文件(只有一个、在游戏加载时才能看到)。 例如:Prefab
Resources File(源文件):某些二进制资源(图片,声音)被单独保存,方便快速加载。 (在本地可以直接看到)如图所示:
- 它是一个AssetBundle对象,我们可以同代码从一个特定的压缩包加载出来的对象。这个对象包含了所有我们当初添加到这个压缩包里面的内容,我们可以通过这个对象加载出来使用。
二、用处:
- AssetBundle相当于一个压缩包包含模型、贴图、预制体声音,甚至整个场景,可以在游戏运行的时候被加载;
- AssetBundle自身保存着互相的依赖关系;
- 压缩包可以使用LZMA和LZ4压缩算法,减少包大小,更快的进行网络传输;
- 把一些可以下载内容放在AssetBundle里面, 可以减少安装包的大小;
三、AssetBundle使用流程。
指定资源的AssetBundle属性设置。
如图:
None: 默认的,表示不打包。
New: 创建打包,(例如:wall、scene/wall、scene/cylinderwall)红色圈圈出是设置文件的后缀。默认为none 如图所示:
打包出来的效果:
Remove Unused Names: (删除没有用的)构建AssetBundle包(重要代码可在Unity官方手册中AssetBundle/AssetBundle Workflow中的Build the AssetBundle)。我下面也写到的。
using UnityEditor; using UnityEngine; using System.IO; public class CreateAssetBundles : MonoBehaviour { [MenuItem("Assets/BuildAssetBundles")] //在Asset菜单栏里添加一个菜单项,命名为BuildAssetBundles static void BuildAllAssetBundles() { //设置路径(在项目的根目录)创建的一个文件夹AssetBundles string dir = "AssetBundles"; //如果没有则创建一个 if (Directory.Exists(dir)==false) { Directory.CreateDirectory(dir); } //参数解释:路径,Build的一个选项,目标平台(例如:Windows,安卓) BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64); } }
3.上传包
4. 加载AssetBundle包和包里的资源
AssetBundle《二》
一、AssetBundle_分组策略
- 把经常更新的资源放在一个单独的包里面,跟不经常更新的包分离
- 把需要同时加载的资源放在一个包里面
- 可以吧其他包共享的资源放在一个单独得包里面
- 把一些需要同时加载的小资源打成包
- 如果对于一个同一个资源有两个版本,可以考虑通过后缀来区分
二、依赖打包
(避免被共享的素材被重复打包)
使用共同的材质打包测试:
- 普通打包,只将物体分别打包。如图:
- 依赖打包,将材质物体分别打包。如图:
显而易见,使用后者将减少空间,并且节省下载速度。(并且unity会自动去寻找依赖关系,不需要再用代码控制。)
构建AssetBundle包(二)
(即Build,接之前所讲)
1. Build:路径(硬盘上随意地址)
2. BuildAssetBundleOptions:(Build的一个选项)
1)全部选项如下地址:
Unity官方手册
2)主要介绍如一下三个:
None:默认(使用LZMA算法压缩,压缩的包更小,但是加载时间更长。使用之前需要整体解压。一旦被解压,这个包会使用LZ4重新压缩。使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,一旦他被下载了之后,它会使用LZ4算法保存到本地上。)
UncompressedAssetBundle:不压缩,包大,加载快
ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是我肯可以加载指定资源而不用解压全部。
注意:使用LZ4压缩,可以获得跟不压缩相媲美的加载速度,而且比不压缩包小。
- BuildTarget:选择build出来的AB包要使用的平台(Android,Windows..)
测试三种压缩方法的包的大小
- None:
- ChunkBasedCompression(LZ4)
- UncompressedAssetBundle
所以一般情况下使用默认的进行压缩
Manifest文件
首先简单的介绍一下里面的内容如图所示:
Asset:包中的内容(图中显而易见是一个预制体)。
Dependencies:依赖(地址)。
其作用是用unity读取该文件来获得该物体所使用的依赖,如果在使用该物体时依赖的包还没有被加载则显示材质丢失,如图:
通过AssetBundle的Manifest文件的到某个包的依赖
//参数:文件夹/文件(这个文件是根据文件夹自动生成的所以名字相同)
AssetBundle manifestAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
AssetBundleManifest manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
测试1:取得所有包名
//foreach (string name in manifest.GetAllAssetBundles())
//{
// print(name);
//}
///取得某个包的依赖
//获取cubewall里面的所有的依赖
string[] str = manifest.GetAllDependencies("cubewall.unity");
foreach (string name in str)
{
AssetBundle.LoadFromFile("AssetBundles/" + name); //加载出来所有的依赖包
}
加载AB包和包里面的资源
简单的介绍一下AssetBundle的使用,大概分为以下四种:
1. AssectBundle.LoadFormMemoryAsync 从内存中加载(Async异步,不带则是同步。)
2. AssectBundle.LoadFormFile 直接从本地文件加载
3. WWW.LoadFormCacheOrDownload 可以从本地/服务器加载(在unity2017之后就不经常使用,可能被弃用使用一下的方式)
4. UnityWebRequest (Unity5.3及以上才可使用) 非常明确就是从web加载
这四种都是静态方法
四种方式实现的方法:
/// <summary>
/// 第一种:从内存中加载(异步/同步)
/// </summary>
AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
//等待加载完成
yield return request;
AssetBundle ab = request.assetBundle;
AssetBundle ab = AssetBundle.LoadFromMemory(File.ReadAllBytes(path));
/// <summary>
/// 第二种:从本地上加载(异步/同步)
/// </summary>
AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(path);
yield return request;
AssetBundle ab = request.assetBundle;
AssetBundle ab = AssetBundle.LoadFromFile(path);
/// <summary>
/// 第三种:WWW (这个也需要使用协程)
/// 可以从本地也可以从服务器
/// 如果从本地把地址前加“file”
/// </summary>
while (Caching.ready == false)
{
yield return null;
}
//返回的www对象,参数为(地址,版本号)
WWW www = WWW.LoadFromCacheOrDownload(wwwPath, 1);
//如果是空字符串,空对象都是没有错误的
if (string.IsNullOrEmpty(www.error) == false)
{
Debug.Log(www.error); yield break; //因为www出现错误不会出现异常而是继续运行,所以要先判断一下。
}
AssetBundle ab = www.assetBundle;
/// <summary>
/// 第四种:使用UnityWebRequest
/// using UnityEngine.Networking;
/// </summary>
UnityWebRequest request = UnityWebRequest.GetAssetBundle(webPath);
yield return request.SendWebRequest(); //等待下载完成
//加载的两种方式
AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
//AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
注意本地的地址写法:`file:// file:/// 都是可以的
string wwwPath = @"file:///E:\UnityProject\Study\AssetBundle_Text\AssetBundles\cubewall.unity";`
四种我读的都是本地,服务器基本是一样的,修改地址即可。
AssetBundle的卸载
减少内存的使用
如果卸载不当则会导致材质的丢失。所以根据以下判断:
AssetBundle.Unload(true):
卸载所有的资源,即使资源被使用着(如:在关卡切换、场景切换。 资源没被使用的时候)。
AssetBundle.Unload(true)
卸载所有没有被适应的资源(通过“Resources.UnloadUnusedAssets.”)。
推荐学习/参考网站:Unity
本作品由A_AiTing采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。