This post is a detailed write-up on what Asset Bundles are in Unity, what they should be used for and how they work internally.
Asset Bundles in Unity are an editor and platform feature that let you configure and deliver dynamic content to your games or apps. You can do "in-game" downloading of external content.
The key use cases for Asset Bundles are:
- Download in-game content during the first run of the game with the goal of minimizing the initial installation size
- Update game content by replacing the asset bundles located on a server - a very poor man's game objects patching system
- You can delivery variants of content for different devices and runtimes - for example differentiate between high-resolution and low-resolution assets, or Android vs Windows assets, potentially allowing you to optimize for devices
- The Asset Bundles API lets you manage what is stored in memory for a potential manual memory management use-case
- Separate the asset bundles from the standard build - the key reason for this could be to reduce build times
What are Asset Bundles?
- They are containers for objects and assets. You can think of them as packages with lots of assets inside.
- Asset Bundles store serialized versions of Unity game objects, such as scenes and everything that a scene could contain.
- An Asset Bundle can contain an entire scene, but if it does - it can't contain anything else (in practical terms).
- Asset Bundles are platform-specific
- Asset Bundles use LZMA or LZ4 compression (depending on the Editor version), which can significantly reduce your build size.
- Asset Bundles use memory. Just in case it is not obvious, the HTTP client needs to download a the bundle (and dump it from memory to disk), release memory, then go about decompressing, which again consumes memory. In big projects we really have to manage this process carefully.
- Asset Bundles are not part of the build output. You execute the bundle separately and deal with the output on your own. Your typical next step is to upload the bundle to a web server (which you also manage on your own) and get your game/app to download it and store it on disk.
The entire Asset Bundles functionality is encapsulated in the following places:
- An Asset Bundle Manager and a (quite crappy) DEV/TEST server, which are delivered through the Unity Asset Store. That's right - you have to "import" it into your game/app. It feels *very* unnatural and more like a hack, however it is understandable why it is implemented that way. It puts the asset build pipeline in total control of the developer.
- The UnityEditor.BuildPipeline class within the UnityEditor.dll assembly. This is where Unity contains coordination logic regarding asset bundles, but the actual bundle packing mechanism is buried in the native part of Unity.
The Asset Bundle Manager
This tool is something you install/import in your game as raw .cs files from the Asset Store. Some scripts are targeted for the Editor experience, while others are examples of how you use asset bundles at runtime in your game/app.
The AssetBundle Manager introduces Editor screens to help you build Asset Bundles. This capability will go over the project hierarchy to detect AssetBundles, then build them in the projects AssetBundles folder.
Since AssetBundles internally use WWW.LoadFromCacheOrDownload, the tooling provides you a local web server, which is a bit too simple, and a Simulation mode so you don't download from a web server.
Apart from the fact that the AssetBundle sample doesn't build with newer versions of Unity (straight from the Asset Store and created and maintained by the Unity team!!), the problem with AssetBundles is that it is written terribly, has TODO's in the code and consumes quite a lot of resources. See below:
The main class itself is called AssetBundleManager. Although every function in it is static, it inherits from MonoBehaviour to make use of the public void Update method called on each frame. The fact that it is not static, yet every function call is static means that you
The Initialize method must be called to load something called the AssetBundleManiifest
All calls to load an asset bundle are classes that inherit the abstract class AssetBundleLoadOperation and get stored into a load queue:
static Dictionary<string, WWW> m_DownloadingWWWs = new Dictionary<string, WWW> ();
The AssetBundleManager class Update method (MonoBehaviour, fires on every frame) checks m_DownloadingWWWs and executes all pending AssetBundleLoadOperations. When done, they are removed from the queue and disposed.
Out of all of the above, probably the only exciting thing is the m_DownloadingErrors Dictionary:
static Dictionary<string, string> m_DownloadingErrors = new Dictionary<string, string> ();
You can use that to check if your download tasks have failed.
Where did the Web Player Asset Bundles go?
As of version 5.3, Unity deprecated the Web Player build target - an in-browser plugin to run Unity games. During the time it still existed, around the 4.0 to 5.3 era, many build pipelines created .unity3d packages. These are Web Player packages in most cases. Some games (such as Hearthstone) use the file extension for their asset bundle build pipeline, but in essence and as far as asset bundling goes, they are asset bundles :)
You can verify this even in the documentation for WWW.LoadFromCacheOrDownload (https://docs.unity3d.com/ScriptReference/WWW.LoadFromCacheOrDownload.html):
The Asset Bundle Manager in 5.4 and later packs files without file extensions. This is fine for most use-cases, however some web file servers require extensions on files. This is why it is a good idea to give them an extension.
You can use tools such as Disunity and Unity Asset Bundle Manager to extract .unity3d files.
Asset Bundle Browser
This is another tool you install from the Asset Store:
Its primary purpose is to help you manage asset bundle dependencies, as well as help you build them with more control:
Apart from that, it is a great set of (badly?) written code samples to help you understand the Asset Bundles API better, so go check them out:
AssetBundle Graph Tool
The Unity team has also released the AssetBundle Graph Tool, a set of editor tools to improve and visualise the AssetBundle workflow and build experience.
There is plenty of reading material on it, so no reason for me to repeat it:
The future of Asset Bundles
This article is written on the 30th of December, 2017 and rechecked in January. At the time of writing, AssetBundle Addressables are not yet released for Unity and the current public version is 2017.3. I'm not part of the Unity team (although I'd love to be) so everything in this heading is taken from the demos performed by the Unity team at Unite events.
- Addressables - The long-awaited replacement of the Resources folder. The idea here is to remove/reduce the overhead of management of AssetBundles through addressable assets and a basic online hosting setup.
- Resource Manager API - a new set of API's designed to work with Addressables to automate dependency loading in a much better way than the current AssetBundle API.
We're expecting releases and fixes to the releases soon. I don't have an ETA for you.
The following are articles you should check out on Asset Bundles:
Good luck with your bundling.