Unity5.4 Assetbundles官方说明一(AssetBundles打包详解)

时间:2022-01-02 04:37:26

转载请注明出处!

    目前网上有一些关于Unity5的Assetbundles不错的中文教程,例如:

1、http://liweizhaolili.blog.163.com/blog/static/16230744201541410275298/阿赵

http://liweizhaolili.blog.163.com/blog/static/162307442015282017852/阿赵

2、http://www.it165.net/pro/html/201506/43896.html

      当时刚学Unity5的Assetbundles的时候,学了好久头绪还是有点乱,后来直接看官方文档的教程,勉强基本掌握了Unity5的Assetbundles的使用。下面就把我在官方文档学到的关于Assetbundles的内容分享给大家,希望对大家有帮助(我用的是Unity5.3版本)。AssetBundle资源包是什么文件,我将不再进行解释,网上也有好多资料的,我将按照官方文档的教程进行详解,希望大家多多指点。PS:本人英语不太好,翻译的不太准确的话,望大家指正并谅解。最后祝大家学习愉快。

  首先特别说明一下:资源包就是指AssetBundle,我们打包后的文件主要就是资源包,而资源是包含在资源包中,也是我们常用的模型、材质、纹理贴图等等资源,接下来的文章中希望大家能分清“资源”和“资源包”这两个名词。

一、打包Assetbundles资源

     开始创建一个AssetBundle,从项目文件夹中选择一个想要打包的资源对象,在Inspector检查器窗口的底部是AssetBundle菜单,从第一个下拉框中选择或设置AssetBundles的名称,第二个下拉框是附加选项,来定义一个变体包,将在下面详解(注意:如果资源是第一次打包,请不要设置第二个附加选项,否则打包报错)。默认情况下,AssetBundle名称设置为None,这意味着资源不能进行AssetBundle打包。如果你还没有定义了一个包,单击New…,输入一个包名。这样就可以创建一个或多个AssetBundles,打包的名字就是设置的名字。

Unity5.4 Assetbundles官方说明一(AssetBundles打包详解)

       AssetBundle名称可以使用“/”符号进行分级,便于管理。在下面的例子中,资源已经被添加到了一个称“environment/desert”的AssetBundle。而这个“environment/desert”的AssetBundle可能包含多个资源,即有多个资源选择了同一个Assetbundle(注意:AssetBundle名字总是小写,如果你使用大写字符的名称,他们被转换为小写)。如果创建的AssetBundles没有分配给资源,即存在没有使用的AssetBundle名称,可以使用“ Remove Unused Names”选项删除未使用的名称。

 

Unity5.4 Assetbundles官方说明一(AssetBundles打包详解)

 

     下面是脚本执行打包Assetbundle资源的代码

/// <summary>
/// 自动打包资源(设置了Assetbundle Name的资源)
/// </summary>
[MenuItem("AssetBundle/Build AssetBundles 01")] //设置编辑器菜单选项
static void BuildAllAssetBundles()
{
//打包资源的路径
string targetPath = Application.dataPath + "/StreamingAssets";

//打包资源
BuildPipeline.BuildAssetBundles(targetPath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);

//刷新编辑器
AssetDatabase.Refresh();
}

     在编辑器找到设置的菜单选项,然后点击这个菜单选项后会调用设置的打包函数,Unity引擎会自动进行打包,即将设置了AssetBundle名称的所有资源和预设,全部打包(注意:需要先手动创建一个要打包资源的路径,否则不能打包。例如:这里我先在项目里创建了StreamingAssets文件夹)。

Unity5.4 Assetbundles官方说明一(AssetBundles打包详解)

 

      然后会在打包的资源路径下找到打包的资源,每个打包的资源名称就是在Unity中选择的Assetbundle名称。此外,每个AssetBundle都有一个扩展名为“.manifest”的关联文件,这是一个文本文件,可以用任何文本编辑器打开查看,它记录了资源的CRC、打包资源的路径、资源之间的依赖关系等信息,并以链式结构记录,修改时只需修改链的其中一环。AssetBundle在上面的官方示例中有一个这样的文件:
Unity5.4 Assetbundles官方说明一(AssetBundles打包详解)
    除了打包的资源文件之外,还创建了另外两个AssetBundle的文件:路径文件夹的AssetBundle文件和manifest文件(例如上面例子中,会在打包的资源路径中找到StreamingAssets和StreamingAssets.manifest两个文件)。他们是为打包资源所在路径的文件夹创建的AssetBundle,所以如果总是在一个路径下打包资源,那么这个路径文件夹中只有这两个额外的文件。其中额外的manifest文件跟其他资源的manifest一样,但是这个文件记录了目录中打包AssetBundle的所有资源信息和依赖信息。(具体的manifest中的信息描述,大家做两遍测试就会大概明白打包记录的信息,在此不详细说明,大家可以参考阿赵的一片日志: http://liweizhaolili.blog.163.com/blog/static/16230744201541410275298/
 

二、Shader的分离打包操作

    当在打包的资源中包含Shader文件时,Unity会根据当前场景和lightmapping的设置来决定使用哪个Lightmap(光照贴图)模式。这意味着在打包时,需要一个配置好的场景并且是打开的场景。

    当然也可以手动指定从哪一个场景中计算Lightmap(光照贴图)的模式。打开想使用的场景,在图形设置Inspector监视器窗口(Edit > Project Settings > Graphics),找到Shader stripping,设置Lightmap modes为Manual,,然后点击From current scene按钮,中间几个单选框会被自动打勾或勾掉。如下图所示(官方):

Unity5.4 Assetbundles官方说明一(AssetBundles打包详解)


三、AssetBundle编辑工具

1、获取AssetBundle的名称

    下面的脚本是显示所有将会被打包的AssetBundle资源名称,并在后台输出。

/// <summary>
/// 查看所有的Assetbundle名称(设置Assetbundle Name的对象)
/// </summary>
[MenuItem("AssetBundle/Get AssetBundle names")]
static void GetNames()
{
var names = AssetDatabase.GetAllAssetBundleNames(); //获取所有设置的AssetBundle
foreach (var name in names)
Debug.Log("AssetBundle: " + name);
}


2、当AssetBundle资源名称发生变化时,会得到通知。(这个脚本无需挂到物体上,会自动检测运行,当改变资源AssetBundle的名称时,会在后台打印出相关信息)

using UnityEngine;
using UnityEditor;

public class MyPostprocessor : AssetPostprocessor
{
//使用AssetPostprocessor类定义的函数OnPostprocessAssetbundleNameChanged回调
//当AssetBundle的名称发生变化时,编辑器会自动执行以下函数,返回变化信息
public void OnPostprocessAssetbundleNameChanged(string assetPath, string previousAssetBundleName, string newAssetBundleName)
{
Debug.Log("Asset " + assetPath + " has been moved from assetBundle " + previousAssetBundleName + " to assetBundle " + newAssetBundleName);
}
}


四、AssetBundle的变体

    这可用于实现类似AssetBundle资源的相同结果。例如,可以设置AssetBundle的变体为“myassets.hd”和“myassets.sd”。在此,Unity为了确保资源完全匹配,打包时BuildPipeline类为这个带有两个变体AssetBundle的资源对象提供了相同的内部ID,现在这两个变种AssetBundles可以任意切换,用AssetBundles的不同变体可以在在运行时扩展(再次说明:如果资源是第一次打包,请不要设置第二个附加选项,否则打包报错)。设置如下图:

Unity5.4 Assetbundles官方说明一(AssetBundles打包详解)


(注意:完整的AssetBundle名字是AssetBundle名字和变体名字的结合。例如:如果添加了一个名为“myassets.hd”的变体AssetBundle,应该设置AssetBundle的名字为“myassets”,变体的名字为“hd”

五、用API的脚本把资源设置为AssetBundle
  官方API给出了一个AssetImporter类(作为特殊资源类型派生资源导入基类),来用脚本对AssetBundle的设置进行一些操作,再次只列举几个用法,用脚本设置AssetBundle的名称和变体名,代码如下:

//注意此处的basePath是Assets开头的路径:Assets/...

AssetImporter importer = AssetImporter.GetAtPath(basePath); //获取要设置的资源导入器
importer.assetBundleName = assetName; //设置AssetBundle名称

importer.assetBundleVarian = assetVarian; //设置AssetBundle变体名

注意:AssetImporter是一个编辑器类,如果想使用它你需要把它放到工程目录下的Assets/Editor文件夹下。编辑器类在UnityEditor命名空间下。所以当使用C#脚本时,你需要在脚本前面加上 “using UnityEditor”引用。

六、 BuildPipeline.BuildAssetBundles()打包方法的基本参数说明
  AssetBundleManifest  BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions = BuildAssetBundleOptions.None, BuildTarget targetPlatform = BuildTarget.WebPlayer);

outputPath 输出路径
assetBundleOptions 打包参数设置,默认是 BuildAssetBundleOptions.None 下方有详解
targetPlatform :打包的目标平台,默认为 BuildTarget.WebPlayer
还有一个重载方法里多了一个参数 AssetBundleBuild[] builds ,这个参数包含了从资源到AssetBundle的映射关系,例如设置AssetBundle名称与Asset名称的映射关系。这提供了一定的灵活性:我们可以通过脚本设置映射信息并在打包时构建映射关系,当然这个映射信息不能替代或更改现有的资源库。个人感觉这个扩展方法不常用,以下是官方提供的例子:
using UnityEngine;
using UnityEditor;

public class BuildAssetBundlesBuildMapExample : MonoBehaviour
{
[MenuItem( "Example/Build Asset Bundles Using BuildMap" )]
static void BuildMapABs( )
{
// Create the array of bundle build details.
AssetBundleBuild[] buildMap = new AssetBundleBuild[2];

buildMap[0].assetBundleName = "enemybundle";

string[] enemyAssets = new string[2];
enemyAssets[0] = "Assets/Textures/char_enemy_alienShip.jpg";
enemyAssets[1] = "Assets/Textures/char_enemy_alienShip-damaged.jpg";

buildMap[0].assetNames = enemyAssets;
buildMap[1].assetBundleName = "herobundle";

string[] heroAssets = new string[1];
heroAssets[0] = "char_hero_beanMan";
buildMap[1].assetNames = heroAssets;

BuildPipeline.BuildAssetBundles( "Assets/ABs", buildMap, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows );
}
}


七、在AssetDatabase资源库中操作AssetBundle的相关API
  • string[] GetAllAssetBundleNames():返回资源库中所有的AssetBundle名称(即我们设置过的名称)
  • string[] GetAssetPathsFromAssetBundle(string assetBundleName):返回Assetbundle名称为assetBundleName的所有资源路径
  • bool RemoveAssetBundleName(string assetBundleName, bool forceRemove):从AssetBundle资源库中删除assetBundleName名称,forceRemovetrue表示就算有资源使用这个名称也会删除,forceRemovefalse表示只删除未使用的AssetBundle名称
  • string[] GetUnusedAssetBundleNames():返回所有未使用的AssetBundle名称
  • void RemoveUnusedAssetBundleNames():删除所有未使用的AssetBundle名称
  • 七、关于BuildAssetBundleOptions打包参数说明

    • CollectDependencies包含所有依赖项(Unity5.x中已过时,被新的打包系统替代,可忽略此项);
    • DeterministicAssetBundle使每个Object具有唯一的、不变的HashID(Unity5.x中已过时,被新的打包系统替代,因为打包的资源都会创建一个ID,可忽略此项);
    • UncompressedAssetBundle在创建AssetBundle包时不压缩的方式打包;
    • DisableWriteTypeTree在AsserBundle包中不包含类型信息;
    • ForceRebuildAssetBundle强制重新打包AssetBundle;新增
    • IgnoreTypeTreeChanges用于判断AssetBundle更新时,是否忽略TypeTree的变化。表示当打包的资源没有变化,但是类型树却发生了改变,那么将不会重新打包AssetBundle,与DisableWriteTypeTree冲突。新增;
    • AppendHashToAssetBundleName这个选项将会在打包的时,将打包出来的资源名称后面自动添加上哈希id;
    • ChunkBasedCompression这个选项表示在打包AssetBundle时使用LZ4进行压缩。当从AssetBundle读取数据时可以实时解压。5.3版本新增。

    • 八、Manifest文件说明

    • ManifestFileVersion:文件的版本信息
    • CRC
    • Hashes:哈希信息,包含两种
    •     (AssetFileHash:资源文件的哈希信息,表示了包含在这个AssetBundle中的所有资源的哈希信息,仅用于重建;
    •     TypeTreeHash:类型树的哈希信息,表示了包含在这个AssetBundle中的所有类型的哈希信息,仅用于重建。)
    • ClassTypes:类的类型值,包含在这个AssetBundle中所有的类的类型值,当进行类型树的增量重建时,这些会用来获取新的哈希值
    • Assets:资源路径名称,包含在这个AssetBundle中的所有资源的路径名
    • Dependencies:依赖的所有Assetbundle的路径名称
      打包AssetBundle后都会创建一个总的Manifest文件,这个文件的名字跟打包的主路径文件夹名称一致,这个总的Manifest只用于增量重建,不是程序运行时必需的。
  •   同时每一个AssetBundle文件都会带有一个Manifest文件,这个文件中包含类型哈希值、资源的路径星系、依赖项的打包信息等。

  • 九、AssetBundle加载的API说明
  • string[] GetAllAssetNames():返回所有AssetBundle的普通资源名,非流形式场景资源。
  • string[] GetAllScenePaths():返回AssetBundle中所有场景资源的路径,只适用于流形式的场景。
  • Object LoadAsset(string name):加载资源对象,还有另外两个重载: Object  LoadAsset (string  name , Type  type )和 LoadAsset (string  name )。
  • Object[] LoadAllAssets():加载Assetbundle中包含的所有资源对象,另一个重载是 Object[]  LoadAllAssets (Type  type )。
    关于AssetBundles在这里只做了简单的说明,如有不当的地方,麻烦大家指正。
   我将在第十一篇中给出完整的项目源码(包括资源的打包、下载资源包、加载资源包、获取资源几依赖资源、使用资源等)。 下一篇将讲解AssetBundle的压缩方式与解压。