zoukankan      html  css  js  c++  java
  • Unity5-ABSystem(二):AssetBundle导出

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/lodypig/article/details/51871510
    方式一编辑器指定
    设置AssetBundle
    导出AssetBundle
    BuildPipelineBuildAssetBundles3
    BuildAssetBundleOptions
    BuildTarget
    Assetbundle变体Variants
    通过脚本设置AssetBundle
    方式二脚本指定
    示例
    AssetBundleBuild结构体
    BuildPipelineBuildAssetBundles4
    补充Mainfest
    TypeTree
    依赖
    本篇主要涉及如何将心仪的资源打包到指定的AssetBundle资源包中。有编辑器指定和脚本指定两种。

    方式一:编辑器指定
    设置AssetBundle
      在Project视图下选择一个资源或文件夹,即可在Inspector面板最下方找到Asset Label面板,点击菜单可以指定该资源所属的AssetBundle名称。


      若要命名一个新的AssetBundle,可点击New创建一个,其他情况则可添加到已有的AssetBundle中。如果你创建了一个AssetBundle,却没有为它指定任何资源,可以使用”Remove Unused Names”,它将移除所有空的AssetBundle。

      在Unity5中,AssetBundle的名称也可以代表相对路径,如图中environment/desert将创建名为desert的AssetBundle在environment目录下。注意,生成AssetBundle时并不会自动创建相应的目录,如果对应目录不存在,本次生成将失败。
      

    导出AssetBundle
      通过以上方式,我们可以设置资源打包成AssetBundle的对应关系,未设置的资源将不会包含在任何AssetBundle中。接着将以下代码添加到任意Editor目录下(如果没有可在任意地方创建一个)。

    using UnityEditor;   

    public class CreateAssetBundles
    {
    [MenuItem ("Assets/Build AssetBundles")] // 在Assets菜单下拓展Build AssetBundles按钮
    static void BuildAllAssetBundles () // 点击该按钮将执行本函数
    {
    BuildPipeline.BuildAssetBundles ("Path"); // 支持路径,如 Asset/AssetBundle
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      编译之后,Assets菜单(编辑器上方或右键Project下资源弹出)即多出了Build AssetBundles,点击后将在Path对应路径导出AssetBundle。你可以换成你喜欢的路径,路径起始于Assets目录,确保该路径存在。
     我们使用了BuildPipeline.BuildAssetBundles接口来导出AssetBundle,这个接口的完全体如下。

    BuildPipeline.BuildAssetBundles/3
    public static AssetBundleManifest BuildAssetBundles(string outputPath,
      BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);
    1
    2
      这里是三参的重载,下面会出现四参的重载。
      参数含义如下:

     outputPath : 导出路径
     BuildAssetBundleOptions  : 导出选项枚举,内容在后面。
     BuildTarget  : 导出平台枚举

      函数返回了一个AssetBUndleManifest类对象,本篇最后会讲到。

    BuildAssetBundleOptions
      None : 没有任何特殊要求。
      UncompressedAssetBundle : 不压缩。
      DisableWriteTypeTree : Assetbundle中不包含Type信息。TypeTree将在后面提到。
      DeterministicAssetBundle : 使用资源的Hash ID来导出AssetBundle。使用ID可避免资源改名、移动位置等导致重新导出。
      ForceRebuildAssetBundle : 强制重新导出。对已有的AssetBundle,在资源没有变化时,Unity不会重新导出。
      IgnoreTypeTreeChanges : 增量打包时忽略Type信息变化。
      AppendHashToAssetBundleName : 在AssetBundle名称后添加”_”加上Hash值。
      ChunkBasedCompression : 使用块压缩,即LZ4压缩。

    BuildTarget
      AssetBundle在不同平台下是不兼容的,对于不同平台的AssetBundle要分别进行导出。BuildTarget用来指定导出平台,例如BuildTarget.iOS。完整的枚举可以在Unity官方手册中找到。
      通常可以使用EditorUserBuildSettings.activeBuildTarget,指定为Unity编辑器当前选择的平台。

    Assetbundle变体(Variants)
     
      之前我们选择性忽略了AssetBundle右边还有一个菜单,这里可以用于指定AssetBundle变体。它有点像虚类的子类实现,用来解决例如在不同平台不同分辨率下使用不同资源的问题。上图中设置将导出myassets.hd,我们可以设置另一个变体为myasset.sd,确保两个AssetBundle中有相对应的资源,Unity将对两个AssetBundle中的资源使用同样的ID,使它们支持在运行时切换。
      更详细内容可以参考Unity官网手册。

    通过脚本设置AssetBundle
      在实际项目中,手动去为每个资源设置其AssetBundel及Variants会带来容易出错,影响心情,不易改动等副作用,所以最好通过脚本去设置。我们可以通过以下脚本设置资源AssetBundle及变体。

    using UnityEditor;

    public class SetAssetBundle {
    public void Example() {
    string path = "Assets/ReplaceMe.asset";
    AssetImporter ai = AssetImporter.GetAtPath(path);
    ai.assetBundleName = "AssetBundleName";
    ai.assetBundleVariant = "Variant";
    }
    }
      // 其效果等价于在编辑器中直接指定
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    方式二:脚本指定
    示例
      除了在编辑器下设置AssetBundle名称外,我们还可以直接使用脚本导出,先感受一下。

    using UnityEditor;
    public class BuildAssetBundle
    {
    static void Example()
    {
    /*
    * 1.创建building map实体
    * 2.指定Assetubndle名称
    * 3.指定变体名称(可选)
    * 4.指定资源路径
    * 5.导出
    */

    AssetBundleBuild abb = new AssetBundleBuild();   
    abb.assetBundleName = "myAssetBundle";
    // abb.assetBundleVariant = "hd";
    abb.assetNames = new string[2] { "Assets/sprite/hello.png", "Assets/sprite/world.png" };
    BuildPipeline.BuildAssetBundles("Assets/AssetBundle", new AssetBundleBuild[1] { abb });
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
      这段代码将”Assets/sprite/hello.png”和”Assets/sprite/world.png”导出到Assets/AssetBundle/myAssetBundle目录下。建议自己在Unity中尝试一下,加深印象,本系列后面我们将默认采用这种方式。

    AssetBundleBuild结构体
      上面导出过程中,我们首先创建了AssetBundleBuild结构体,这个结构体长下面这样:

    namespace UnityEditor
    {
    // AssetBundle building map 实体.
    public struct AssetBundleBuild
    {
    public string assetBundleName; // AssetBundle 名称.
    public string assetBundleVariant; // AssetBundle 变体.
    public string[] assetNames; // 该AssetBundle包含的资源路径列表。
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      一个AssetBundleBuild实体对应一个AssetBundle资源包。而我们只要生成好多好多这样的实体,为他们指定包含的资源列表,再一次性拿去给BuildPipeline.BuildAssetBundles让他干活就好了。

    BuildPipeline.BuildAssetBundles/4
      相较于3参的,这里多出了一个AssetBundleBuild[] builds,对应上面创建的AssetBundleBuild对象,一个AsssetBundleBuild最终会导出一个AssetBundle,而列表代表我们可以一次导出多个AssetBundle。

    public static AssetBundleManifest BuildAssetBundles(string outputPath, AssetBundleBuild[] builds,
      BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);
    1
    2
    补充:Mainfest
      如果有运行上面代码,就会发现每导出一个AssetBundle文件,就会送一个同名的.manifest文件。除此之外,在BuildAssetBundles接口参数outputPath目录下,还自动生成了与目录同名的AssetBundle及.manifest文件。Manifest只是一个文本文件,可以用任何文本编辑器打开,他提供了诸如CRC和资源依赖的信息。一个Mainfest可能会长这样:

    ManifestFileVersion: 0
    CRC: 2422268106
    Hashes:
     AssetFileHash:  
       serializedVersion: 2
       Hash: 8b6db55a2344f068cf8a9be0a662ba15
     TypeTreeHash:
       serializedVersion: 2
       Hash: 37ad974993dbaa77485dd2a0c38f347a
    HashAppended: 0
    ClassTypes:
    - Class: 91 
     Script: {instanceID: 0}
    Assets:  (资源列表)
     Asset_0: Assets/Mecanim/StateMachine.controller
    Dependencies: {} (依赖列表)

      至于与目录同名的.manifet文件,提供了所有AssetBundle之间依赖关系,我们可以叫它总manifest文件。而那个不请自来的AssetBundle中包含的就是总manifeset文件。
      一份存在依赖关系的总manifest可能长下面这样。列举了每一个AssetBundle和其依赖的AssetBundle列表。

    ManifestFileVersion: 0
    AssetBundleManifest:
    AssetBundleInfos:
    Info_0:
    Name: image.ab
    Dependencies: {}
    Info_1:
    Name: none.ab
    Dependencies: {}
    Info_2:
    Name: sprite1.ab
    Dependencies:
    Dependency_0: common.ab
    Info_3:
    Name: sprite123.ab
    Dependencies:
    Dependency_0: common.ab
    Info_4:
    Name: sprite1234.ab
    Dependencies:
    Dependency_0: common.ab
    Info_5:
    Name: sprite2.ab
    Dependencies:
    Dependency_0: common.ab
    Info_6:
    Name: sprite234.ab
    Dependencies:
    Dependency_0: common.ab
    Info_7:
    Name: sprite3.ab
    Dependencies:
    Dependency_0: common.ab
    Info_8:
    Name: sprite4.ab
    Dependencies:
    Dependency_0: common.ab
    Info_9:
    Name: common.ab
    Dependencies: {}

    TypeTree
      Manifeset里面还有一些如Class ID的字样,指的是AssetBundle的TypeTree。关于TypeTree的资料非常少,可以知道它记录了一个Class ID,Class ID对应的Class可以在这里找到,Unity利用Class ID来序列化或反序列化一个类,这份信息也可以包含在引擎里,所以AssetBundle导出时有一个选项可以不导出这部分,可以轻微减少包大小和提高加载速度。

    依赖
      上面提到了很多次AssetBundle依赖,而AssetBundle依赖可以说是Unity AssetBundle系统中最大两坑之一,所以将再后面另开一篇。
    ————————————————
    版权声明:本文为CSDN博主「lodypig」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/lodypig/article/details/51871510

  • 相关阅读:
    (0)git安装
    [SCOI2008]奖励关
    bzoj1007 [HNOI2008]水平可见直线
    【bzoj1060】[ZJOI2007]时态同步
    【bzoj2705】[SDOI2012]Longge的问题
    【bzoj3505】[Cqoi2014]数三角形
    【bzoj3747】[POI2015]Kinoman
    P1072 Hankson的趣味题
    poj1845 数论 快速幂
    【bzoj1965】[Ahoi2005]SHUFFLE 洗牌
  • 原文地址:https://www.cnblogs.com/yptianma/p/11776000.html
Copyright © 2011-2022 走看看