[EDIT]
This post is now OBSOLETE!
Please visit this page for up-to-date details.
__*http://unity3d.com/learn/tutorials/topics/scripting/assetbundles-and-assetbundle-manager?playlist=17117*__
To discuss this topic, please use this thread:
__*The AssetBundle Manager Tutorial Q&A - Learn Content & Certification - Unity Discussions
[/EDIT]
In Unity 5.0, we have a new AssetBundle build system which is much more easier to use than the old one.
Basic Introduction
In the new AssetBundle build system, we provide:
-
Simple UI to mark the assets into an AssetBundles, and keep the assets to AssetBundles mapping in the asset database.
-
You can find the UI at the bottom of the asset preview panel. It’s very simple, just try to use it.
-
The AssetBundle name will be stored in the meta file.
-
Also provide search filter in the search bar, you can type “b:” to search assets with given AssetBundle name.
-
Some restrictions:
-
Don’t allow mark one asset into multiple AssetBundles.
-
You can only set a relative path as the AssetBundle name.
-
You cannot mark scripts into AssetBundles.
-
You cannot mark scene asset and normal asset in a same AssetBundle.
-
API to mark the asset into AssetBundle
-
You can use AssetImporter.assetBundleName to set the AssetBundle name.
-
Simple APIs 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 & 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. We generate the manifest file 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 also provided
-
We won’t return component type any more, please load the game object first and then look up the component on the object.
-
Typetree is written to the AssetBundle by default. The only exception is Metro as it has different serialization solution.
The above is the basic usage of how to use the new AssetBundle build system. What can you benefit from it?
-
No complex building script any more.
-
Unity handles the dependencies.
-
This means you don’t need to handle the dependencies by using PushAssetDependencies/PopAssetDependencies functions, as Unity knows all the dependencies and handles this for you. This can reduce a lot of your efforts.
-
Incremental build check which means you only need to rebuild the AssetBundle which actually change. This includes two parts:
-
Incremental build check for asset file changes. We generate a single hash for all the assets in the AssetBundle. Only when the assets in the AssetBundles actually change, we will do the rebuild.
-
Incremental build check for type tree changes. We also generate a single hash for the type trees in the AssetBundle. By default, we will rebuild the AssetBundle if type tree changes, but you can ignore the type tree changes by setting IgnoreTypeTreeChanges flag.
-
Don’t force rebuild all the AssetBundles on the dependency chain.
-
We change the way how we store dependent objects, this allow you not rebuild all the AssetBundles on the dependency chain.
-
Let’s have an example, we have a cube prefab which has a material which has a texture. If we mark the cube prefab into CubeAssetBundle, and mark the material into MaterialAssetBundle, then we change the texture on the material. In the old build system, we need to rebuild both the CubeAssetBundle and MaterialAssetBundle, as we need to rebuild the dependent objects. But in the new build system, we only need to rebuild the MaterialAssetBundle without rebuilding CubeAssetBundle.
Btw: The new and the old build systems will coexist for a while, PLEASE DON’T MIX THEM WHEN YOU’RE BUILDING ASSETBUNDLES.
AssetBundle Variant
Another thing I want to describe a little more is AssetBundle variant. From Unity 5.0 b21, we have better AssetBundle variant support in the new build system, which can be used to achieve the same result as virtual assets.
For example, you can set AssetBundle as variants like “MyAssets.hd”, “MyAssets.sd”(Make sure the assets exactly match in these two AssetBundles). 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.
Then how to set the AssetBundle variant?
- From UI. From Unity 5.0 b21, beside the AssetBundle Name UI, we add one more UI to set the variant name of the AssetBundle
- AssetImporter.assetBundleVariant. Except UI, you can also set the AssetBundle variant from script.
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. And apparently “MyAssets”+“hd” and “MyAssets.hd”+”” cannot coexist as they lead to the same full AssetBundle name.
Btw: It’s not compatible with the Editor simulation.
Demo
Based on the new build system, we also made a demo to demonstrate the usage of current AssetBundle system. You can download the demo at the below link, let me know if you can’t access it. And please based on Unity 5.0 b21 to run this demo.
[EDIT]
This is the up-to-date AssetBundle Manager Demo:
http://unity3d.com/learn/tutorials/topics/scripting/assetbundles-and-assetbundle-manager?playlist=17117
This link is obsolete:
http://files.unity3d.com/vincent/assetbundle-demo/users_assetbundle-demo.zip
[/EDIT]
It demonstrates:
- How to build AssetBundles in the new build system.
- How to use the single manifest AssetBundle.
- Automatic AssetBundle dependency resolving, loading & unloading.
- Editor simulation. With it enabled, you can use AssetBundles in Editor play mode without actually building them.
- Optional setup where to download all AssetBundles.
- Build pipeline build integration. Script to build the AssetBundles and copy them to StreamingAssets folder, then they can be packed into the player data when you’re building the player. Please use the “AssetBundles/Build Player” to build the player data.
- New version of WWW.LoadFromCacheOrDownload and feed 128 bit hash to it when downloading. You can get the hash from the single manifest AssetBundle.
- AssetBundle variant to achieve the same result as virtual assets. (It’s not compatible with the Editor simulation.)
Please refer to the README file in the demo project to get more details on this.
Any feedback are appreciated.