当前位置:首页 » 计算机系统

Unity 5.x AssetBundles新系统用法

2015-08-05 18:26 本站整理 浏览(1006)


BuildingAssetBundles in 5.x


Authoring AssetBundles

In Unity 4.x AssetBundles were created using editor scripts. To simplify this process Unity 5.x Editor includes AssetBundle authoring tools. Now, if you select an Asset in the editor a drop down will appear at the bottom of the Inspector window inviting you
to specify which AssetBundle (if any) the asset should be packaged into. By default the AssetBundle option is set to None, meaning the asset will not be written into an AssetBundle. You can create new AssetBundle, give them names, and then use these new AssetBundle
names as the destination for the asset.

AssetBundle creation
In the picture the StateMachine asset has been added to an AssetBundle called scene1/animdata. This AssetBundle may contain other assets which have previously been added.
Empty AssetBundles can be created by using the “New…” menu option. After you have created a new, empty AssetBundle it will appear in the list allowing you to add assets to it. AssetBundle names are always lower-case. If you use upper-case characters in the
name they will be converted to lower-case. Using a forward slash in the name of the AssetBundle effectively creates folders, and the menu will have sub-menus, as the picture above shows.
If you create AssetBundles which have no assets assigned to them, then the “Remove Unused Names” option can be used. This will delete the empty AssetBundle.
The meta file belonging to an Asset will have the chosen AssetBundle name written into it.


Exporting AssetBundles

AssetBundles are exported from the editor using script code. (This is similar to the 4.x approach.) The following script exports AssetBundles:
[code]using UnityEditor;

public class CreateAssetBundles
{
    [MenuItem ("Assets/Build AssetBundles")]
    static void BuildAllAssetBundles ()
    {
        BuildPipeline.BuildAssetBundles ("AssetBundles");
    }
}

This script creates a menu item at the bottom of the Assets menu. When that menu item is selected the function will be called and the AssetBundles will be built. This will start a build dialog with a progress bar. The BuildPipeline.BuildAssetBundles function
will create the AssetBundles into an output folder called “AssetBundles”. This folder must have been created in the project folder. Within that folder the AssetBundles that have been labelled will be created.
Each AssetBundle that is exported will have the name created in the AssetBundle menu. Additionally, each AssetBundle will have an associated file with a .manifest extension. This manifest file is a text file that you can open with any text editor. It provides
information such as the file CRC and asset dependencies. The AssetBundle in the example above has a manifest file that looks like this:
[code]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: {}

In addition to these, there are another two files created: another AssetBundle and another manifest file. These two are always created whenever AssetBundles are created. They are created for each folder that AssetBundles are created in, thus if you always create
AssetBundles in the same place, you will only get two extra files. The additional manifest file - in this example AssetBundles.manifest - can be used in much the same way as other manifest files but will show information on how AssetBundles relate and depend
on each other. In this case, since we only have a single AssetBundle, it has no other dependencies.
[code]ManifestFileVersion: 0
AssetBundleManifest:
  AssetBundleInfos:
    Info_0:
      Name: scene1assetbundle
      Dependencies: {}


AssetBundle Editor Tools


Getting names of AssetBundles

The following editor script can display the names of the AssetBundles which the build process can create.
[code]using UnityEditor;
using UnityEngine;

public class GetAssetBundleNames
{
    [MenuItem ("Assets/Get AssetBundle names")]
    static void GetNames ()
    {
        var names = AssetDatabase.GetAllAssetBundleNames();
        foreach (var name in names)
            Debug.Log ("AssetBundle: " + name);
    }
}


Getting told when an asset changes AssetBundle

You can use the OnPostprocessAssetbundleNameChanged method from the AssetPostprocessor class, to get a callback when the AssetBundle an asset is associated with changes.
[code]using UnityEngine;
using UnityEditor;

public class MyPostprocessor : AssetPostprocessor {

    void OnPostprocessAssetbundleNameChanged ( string path,
            string previous, string next) {
        Debug.Log("AB: " + path + " old: " + previous + " new: " + next);
    }
}


AssetBundle Variants

AssetBundle Variants is a new 5.x feature. This can be used to achieve a result similar to virtual assets. For example, you can set AssetBundle a variants like “MyAssets.hd” and “MyAssets.sd”. Make sure the assets exactly match. The objects in these two variant
AssetBundles will have the exactly same internal IDs which is ensured by the Unity build pipeline. So these two variant AssetBundles can be switched out arbitrarily with AssetBundles of different variant extension at runtime.
How to set assetbundle variants: 1. From the editor use the one extra variant name, to the right of the asset labels GUI. 2. In code use AssetImporter.assetBundleVariant option.

AssetBundle variants
The full AssetBundle name will be the combination of the AssetBundle name and the variant name. For example, if you want to add “MyAssets.hd” as a variant AssetBundle, you should set the AssetBundle name to “MyAssets” and AssetBundle variant to “hd”. And the
final AssetBundle is “MyAssets.hd”.
But if you only set the AssetBundle name like “MyAssets.hd”, then it’s just a normal AssetBundle which is not variant AssetBundle. “MyAssets”+“hd” and “MyAssets.hd”+”” cannot coexist as they lead to the same full AssetBundle name.


Scripting Advice


API to mark the asset into AssetBundle

You can use AssetImporter.assetBundleName to set the AssetBundle name.


Simple APIs

Simple APIs are available to build AssetBundles, BuildPipeline.BuildAssetBundles(). These APIs are pretty
simple, you only need to provide:
Output path for all the AssetBundles.
BuildAssetBundleOptions which will be described later.
BuildTarget which is same as before.
Also have one overloaded version to provide an array of AssetBundleBuild which contains one map from assets to AsssetBundles. This provides flexibility to you, you can set your mapping information by script and build from it. And this mapping information won’t
break/replace the existed one in the asset database.


APIs to manipulate AssetBundle names in the asset database

AssetDatabase.GetAllAssetBundleNames() which returns all the AssetBundle names in the asset database.
AssetDatabase.GetAssetPathsFromAssetBundle to return the asset paths marked in the given AssetBundle.
AssetDatabase.RemoveAssetBundleName() which removes a given AssetBundle name in the asset database.
AssetDatabase.GetUnusedAssetBundleNames() which returns the unused AssetBundle names.
AssetDatabase.RemoveUnusedAssetBundleNames() which removes all the unused AssetBundle names in
the asset database.
AssetPostProcessor.OnPostprocessAssetbundleNameChanged callback which will be called
if user change the AssetBundle name of an asset.


BuildAssetBundleOptions

CollectDependencies and DeterministicAssetBundle are
always enabled.
CompleteAssets is ingored as we always start from assets rather than objects, it should be complete
by default.
ForceRebuildAssetBundle is added. Even there is no change to the assets, you can force rebuild
the AssetBundles by setting this flag.
IngoreTypeTreeChanges is added. Even type tree changes, you can ignore the type tree changes
with this flag.
DisableWriteTypeTree conflicts with IngoreTypeTreeChanges.
You can’t ignore type tree changes if you disable type tree.


Manifest file

A manifest file is created for every AssetBundle which contains the following information:
The manifest file is next to the AssetBundle.
CRC
Asset file hash. A single hash for all the assets included in this AssetBundle, only used for incremental build check.
Type tree hash. A single hash for all the types included in this AssetBundle, only used for incremental build check.
Class types. All the class types included in this AssetBundle. These are used to get the new single hash when doing the type tree incremental build check.
Asset names. All the assets explicitly included in this AssetBundle.
Dependent AssetBundle names. All the AssetBundles which this AssetBundle depends on.
This manifest file is only used for incremental build, not necessary for runtime.


Single manifest file

We generate a single manifest file which includes:
All the AssetBundles.
All the AssetBundle dependencies.


Single manifest AssetBundle

It only contains an AssetBundleManifest object which has following APIs:
GetAllAssetBundles() which returns all the AssetBundle names in this build.
GetDirectDependencies() which returns the direct dependent AssetBundle names.
GetAllDependencies() which returns all the dependent AssetBundle names.
GetAssetBundleHash(string) which returns the hash for the specified AssetBundle.
GetAllAssetBundlesWithVariant() which returns all the AssetBundles with variant.


AssetBundle loading APIs changed

Now we have:
AssetBundle.GetAllAssetNames(). Return all the asset names in the AssetBundle.
AssetBundle.GetAllScenePaths(). Return all the scene asset paths if it’s a streamed scene AssetBundle.
AssetBundle.LoadAsset(). Load asset from AssetBundle.
AssetBundle.LoadAllAssets().
AssetBundle.LoadAssetWithSubAssets().
Asynchronous version are also provided.
Component type are no longer returned. Instead load the GameObject first and then look up the component(s) on the object.


Typetrees

A typetree is written to the AssetBundle by default. The only exception is Metro as it has different serialization solution.