How to build asset bundles with uTomate
|This tutorial applies to Unity 4 or earlier versions. The asset bundle system has been massively improved in Unity 5. If you are using Unity 5, simply set up your asset bundles as specified in the Unity manual and then use the new Build Asset Bundles From Asset Database action to build your defined asset bundles.|
What are Asset Bundles and why would I want to use them?
The simplest way to answer this question is having a look at the Unity manual.
AssetBundles are a collection of assets, packaged for loading at runtime. With Asset Bundles, you can dynamically load and unload new content into your application. AssetBundles can be used to implement post-release DLC. They can also be used to reduce the amount of space on disk used by your game, when first deployed. It can also be used to add new content to an already published game.
Asset Dependencies - The Theory
When you build asset bundles you usually want them to be of minimal size. Therefore you don’t want to include all dependencies of a scene or an asset into each asset bundle, as this will duplicate all the assets and will unnecessarily add to the size of your bundles.
Unity provides a concept called Dependency Stack for this. This concept is not necessarily intuitive ( see the Unity manual for the gory details) but it allows for a great deal of flexibility. The basic idea of the dependency stack is that all bundles, which are on the same or higher stack level as previously built bundles, will share assets from previously built bundles. Now that is probably somewhat abstract so let’s use an example for this.
Let’s assume you got a level called "Level1" from which you can access two versions of another level, called "Level 2a" and "Level 2b". Let’s also assume that in Level 1 you need a robot mesh and textures and Levels 2a and 2b require the same robot mesh and texture but additionally require a car model and textures. Now we want to build asset bundles for Levels 1, 2a and 2b. If you simply build asset bundles without using the dependency stack, each bundle will contain all the dependencies of the level, that is, you get three bundles looking like this:
This is very inefficient because it includes the robot model and textures into Levels 2a and 2b even though it is
already known since Level 1 has been loaded before Levels 2a and 2b. To change this, you can use the dependency stack.
You enable the dependency stack by calling
BuildPipeline.PushAssetDependencies before building a bundle. This will
create a new level on the dependency stack.
Now each bundle that is built will share it’s dependencies with previously built bundles that are on the same or a lower stack level. Let’s see how the dependency makes the bundles smaller:
As you can see, the Level 2a bundle now no longer contains the robot model and textures but shares them with the Level 1 bundle. Unity will do no magic for you though, so you are responsible for loading these bundles in the correct order in your application. Level 2b get’s even smaller as it shares the car model and textures with Level 2a (as 2a got built before 2b on the same stack level).
Now while this yielded some nice savings in bundle space it isn’t exactly what we need. Using this structure makes Level 2b depend on Level 2a. So you will always have to load Level 2a before you can switch to Level 2b otherwise the car model and textures will be missing. Since you can go to either Level 2a or 2b from Level 1 this setup is not useable for our example.
Basically we need the car model and texture in both bundles, the one for Level 2a and the one for Level 2b. To do this,
you can use
BuildPipeline.PushAssetDependencies once before you build the bundle for Level 2a. This will move this
onto a higher dependency stack level. It will still share resources from the Level 1 bundle (as this is on a lower stack
level). After you have built the bundle for Level 2a, you call
BuildPipeline.PopAssetDependencies. This will remove
the higher dependency stack level and therefore future bundles will not share resources with the Level 2a bundle
(remember, bundles only share dependencies with bundles on the same or a lower stack level).
This approach works for streamed scene asset bundles as well as for simple asset bundles and players.
How to do it with uTomate
Usually when you want to build asset bundles there is no way around scripting this. Unity provides a simple UI for building asset bundles which lets you select a few files and build an asset bundle from the selection. But this is not sufficient in two ways. First, if you happen to forget to select a certain file that should be in your asset bundle you will notice that only when you test your game online - which less than optimal. Second, the Unity UI does not support modifying the dependency stack, so building asset bundles that depend on each other is not possible using the UI. So scripting this is the way to go (and even the Unity documentation recommends that you build a function for creating your asset bundles).
With uTomate you can do all of this without scripting with the familiar Unity inspector UI. uTomate provides two actions that can interact with asset bundles - the obvious Build Asset Bundle action and the Build Player action. Both actions provide options to modify the dependency stack:
Basically if you tick Push Dependencies uTomate will put a new level on the dependency stack (by calling
PushAssetDependencies). When you tick Pop Dependencies uTomate will drop a level from the dependency stack (by
PopAssetDependencies). The Pop All Dependencies flag will clear the dependency stack.
So to build the asset bundles from the example, we need three actions that build the asset bundle for the Levels 1, 2a
and 2b. Let’s start with the action for
Its building an asset bundle for the full
Level1 scene and all it’s dependencies. To make sure that the dependency
stack is opened, we have ticked the Push Dependencies flag. Now lets continue with the bundle for
To make sure that everything that is included in this bundle will not be skipped by the
Level2b bundle (since we
want both bundles to be independent of each other) we open a new level on the dependency stack by ticking Push
Dependencies. We also tick Pop Dependencies, to make sure that new level on the dependency stack is cleared once we
finish building the bundle. Apart from this, the setup is basically the same as for
except that we use a different scene here. Finally the action for
Here we tick Pop Dependencies to clean up the dependency stack. This is just good practice to ensure that other
actions that might come afterwards don’t accidentally reference to asset bundles to which they should not reference.
The rest of the setup is the same as for
Level2a, except again we use a different scene here.
Now that our actions are set up, all we need to do is putting them into an automation plan:
|I have added a few notes and arranged the actions to visualize the dependency stack levels. This is just a visual help to show how the plan is supposed to work, it is not required to format it this way to make it work. However having a good documentation on your automation plans makes it easier for everyone on the team to understand how it’s supposed to work (see also our article on building robust automation plans).|
Now with the plan set up, all you need to do is to run the plan and have your asset bundles built. Since you automated this you will get repeatable, consistent results as opposed to the error-prone manual building of asset bundles. Automating this with uTomate instead of scripting also provides a few bonuses:
You don’t need any scripting experience to do it, so every team member can understand and modify the building process.
The automation plan provides a nice visual documentation on what asset bundles you build and how they depend on each other.
If you would like to give us feedback on this tutorial shoot us a mail. We’d also like to hear from you if you would like to see a tutorial about a special topic here.