一、什么是AssetBundle?
1.它存在于硬盘上的文件。可称之为压缩包。该压缩包里面有多个文件,这些文件可分为两类:serialized file和resources file(即序列化文件和源文件)。(1)serialized file:资源被打散放在一个对象中,最后统一被写进一个单独的文件(只有一个)(如:模型资源,prefab资源等)(2)resources file:某些二进制资源(如:图片、声音)被单独保存,方便快速加载。
2.它是一个AssetBundle对象,我们可以通过AssetBundle类从压缩包加载出来对象并使用,这个对象包含了所有当初添加到这个压缩包里面的内容。
下图是我从官网上扣过来的,有兴趣的自己可以去官网上看看。
二、AssetBundle的工作流程
一般情况下。AssetBundle的工作流程大致如下:
(1)开发过程中,开发者创建好AssetBundle文件并上传至服务器上。过程如下图:
(2)游戏运行时,客户端会根据实际需求从服务器上将适当的AssetBundle下载到本地机器,再通过加载模块将其资源加载到游戏当中。
Unity在Build时会自动处理依赖关系,并生成一个.mainfest文件,以及负责AssetBundle的增量式发布。
三、创建AssetBundle文件
在打包时,还需要根据具体的项目需求决定要采用哪种打包策略,与项目的更新与维护息息相关,需慎重!!以下是仅供参考的策略:
1.AssetBundle分组策略(仅供参考)
(1)逻辑实体分组
a.一个UI界面或者所有UI界面一个包(这个界面里面的贴图和布局信息一个包)
b.一个角色或者所有角色一个包(这个角色里面的模型和动画一个包)
c.所有场景所共享的部分一个包(包括贴图和模型)
(2)按照类型分组
所有声音资源一个包,所有shader一个包,所有模型打成一个包,所有材质一个包
(3)按照使用分组
把在某一时间内使用的所有资源打成一个包。可以按照关卡分,一个关卡所需要的所有资源包括角色、贴图、声音等打成一个包。也可以按照场景分,一个场景所需要的资源一个包。
2.AssetBundle打包操作
(1)在Inspector视图下方会出现一个AssetBundle的UI,其中第一个选项表示该资源所标记的AssetBundle名称(即该资源会打包到这个名称的AssetBundle中),第二个参数用于设置AssetBundle Variant,主要应用在不同的版本资源的使用和动态替换AssetBundle。
再通过BuildPipeline类的BuildAssetBundles方法实现打包,该方法说明如下:
// Summary:
// 所有打包操作需要在编辑器模式下,打包代码也需要放在Editor文件夹下
// outputPath:输出路径,即工程目录下面的路径,比如:outputPath="AssetBundles";则AB包的路径为:E:\Unity3D\TestAPI\AssetBundles
// assetBundleOptions:AB包发布选项.
// targetPlatform:选择发布平台.
// Returns:返回一个包含发布所有信息的AssetBundleManifest对象
public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);
(2)BuildAssetBundleOptions枚举类
- None:构建AssetBundle没有任何特殊的选项
- UncompressedAssetBundle:不进行数据压缩。没有压缩/解压的过程,AssetBundle的发布和加载会更快,但是AssetBundle也会更大,导致下载速度变慢。
- CollectDependencies:包括所有依赖关系的资源
- DisableWriteTypeTree:在AssetBundle中不包含类型信息。需要注意的是,如果要将AssetBundle发布到Web平台上,则不能使用该选项。
- DeterministicAssetBundle:使每个Object具有唯一不变的hash ID,可用于增量式发布AssetBundle。
- ForceRebuildAssetBundle:强制重新Build所有的AssetBundle。
- IgnoreTypeTreeChanges:忽略TypeTree的变化,不能与DisbaleTypeTree同时使用。
- AppendHashToAssetBundleName:附加Hash到AssetBundle名称中。
- ChunkBasedCompression:使用LZ4压缩算法来Build AssetBundle。默认LZMA压缩。
- StrictMode:如果发布过程中有任何错误报告就不允许发布成功。
- DryRunBuild:
- DisableLoadAssetByFileName:不允许AB包通过文件名加载资源。
- DisableLoadAssetByFileNameWithExtension:禁用通过使用扩展名加载AssetBundle。
在Editor模式下,Unity为每个AssetBundle都会生成一个Mainfest文件,Manifest文件中包含:CRC(cyclic redundancy check),所包含的Assets,所依赖的AssetBundles,Hash,ClassTypes等。
(1)AssetBundleManifest的访问接口如下:
1.public string[] GetAllAssetBundles():获取所有的AssetBundles的名字。
2.public string[] GetAllAssetBundlesWithVariant():获取所有指定的Variant的AssetBundles的名字
3.public string[] GetAllDependencies(string assetBundleName):获取所给定AssetBundle所依赖的AssetBundles名字
4.public Hash128 GetAssetBundleHash(string assetBundleName):获取所给定AssetBundle的Hash值
5.public string[] GetDirectDependencies(string assetBundleName):获取所给定AssetBundle直接依赖的AssetBundles
了解上述过程之后,打包示例如下:
(1)在Unity的Assets文件夹下选中一个资源,然后在Inspector视图下方设置AssetBundle名称,操作如下图:
图1-Cube设置AB参数
图2-CubeWall设置AB参数
图3-CubeWall设置AB参数,产生依赖关系
(2)在Assets文件的Editor文件夹(没有就创建一个)中创建一个C#脚本,代码如下:
using UnityEditor;
using System.IO;
public class CreateAssetBundles{
[MenuItem("Assets/Build AssetBundles")]//编辑器扩展
static void BuiledAllAssetBundles()
{
string dir = "AssetBundles";
if (Directory.Exists(dir) == false)
{
Directory.CreateDirectory(dir);
}
BuildPipeline.BuildAssetBundles(dir,BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows64);
}
}
(3)选择菜单栏中的Assets→Build AssetBundles命令,既可以在输出路径看到打包好的AB包。效果如图所示:
对资源打包后,输出路径有一个总的Manifest文件,文件名与文件所在的文件夹名称相同,每一个打包的资源分别有一个自己的Manifest。总的Mainfest文件内容如下:
AssetBundles.manifest
ManifestFileVersion: 0
CRC: 440306606
AssetBundleManifest:
AssetBundleInfos:
Info_0:
Name: cube.unity3d//AssetBundle的名称
Dependencies: {}
Info_1:
Name: scene/wall.unity3d
Dependencies:
Dependency_0: scene/material//表示该AssetBundle所依赖的AssetBundle,如果为空则,表示没有依赖
Info_2:
Name: scene/material
Dependencies: {}
四、如何下载AssetBundle
1.非缓存机制
通过创建一个WWW实例来对AssetBundle文件进行下载。下载后的AssetBundle文件不会保存在Unity引擎特定的缓存区。代码如下:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
IEnumerator Start()
{
//从指定的Url下载
WWW www = new WWW("http://myserver/myBundle.unity3d");
yield return www; //等待下载完成
// Get the designated main asset and instantiate it.
Instantiate(www.assetBundle.mainAsset);
}
}
2.缓存机制
通过WWW.LoadFromCacheOrDownload接口下载AssetBundle文件。下载后的AssetBundle文件将自动被保存在Unity引擎特定的缓存区内,该方法是Unity推荐的AssetBundle文件下载方式。Unity提供的默认缓存大小根据发布平台的不同而不同的。
public static WWW LoadFromCacheOrDownload(string url, int version);
public static WWW LoadFromCacheOrDownload(string url, int version, uint crc);
public static WWW LoadFromCacheOrDownload(string url, Hash128 hash, uint crc);
public static WWW LoadFromCacheOrDownload(string url, CachedAssetBundle cachedBundle, uint crc);
参数如下:
1.url:如果不存在于缓存中,则从URL中下载AssetBundle。URL必须经过“%”转义。
2.version:AssetBundle的版本号。如果之前已经下载了相同版本的参数,那么这个文件只会从磁盘缓存中加载。通过增加应用程序请求的版本号,可以强制缓存从url中下载AssetBundle的新副本。
3.hash:作为AssetBundle的版本的Hash值。
4.cachedBundle:用于将给定AssetBundle的版本下载到自定义缓存路径。
5.crc:未压缩内容的一个可选的crc-32校验和。如果这是非零的,那么在加载它之前,内容将与校验和进行比较,如果不匹配,则会给出一个错误。您可以使用它来避免来自错误下载的数据损坏,或者用户篡改磁盘上的缓存文件。如果CRC不匹配,Unity将尝试重新下载数据,如果服务器上的CRC不匹配,它将会失败。查看返回的错误字符串,以查看用于AssetBundle的正确CRC值。
示例代码如下:
using UnityEngine;
using System.Collections;
public class LoadFromCacheOrDownloadExample : MonoBehaviour
{
IEnumerator Start()
{
while (!Caching.ready) //缓存是否就绪
yield return null;
var www = WWW.LoadFromCacheOrDownload("http://myserver.com/myassetBundle.unity3d", 5);
yield return www; //等待下载完成
if (!string.IsNullOrEmpty(www.error))
{
Debug.Log(www.error);
yield return null;
}
var myLoadedAssetBundle = www.assetBundle;
var asset = myLoadedAssetBundle.mainAsset;
}
}
五、AssetBundle的优点
1.降低安装程序的大小
2.有利于游戏的更新与维护。