Asset Bundle Usage in Unity

Unity has many useful features, one of them is support for Asset Bundles.

What Are Asset Bundles?

Asset Bundles are files that contain game assets, from simple assets such as 3D models, textures, and audio clips, to more complex ones, such as Scenes and Prefabs.

Scripts however cannot be included in Asset Bundles, only their references, so be careful when renaming or moving them, as it will break the connection and you'll need to rebuild the Asset Bundles to make them work again.

When to Use Asset Bundles?

Use Asset Bundles when your game has a lot of assets and including them in the build affects the initial download time.

Exporting Asset Bundles

Exporting Asset Bundles is done in two steps: assigning Asset Bundle names and building them using the Editor script.

Assigning Asset Bundle names

To assign the Asset Bundle name, select the asset in the Project view (this can be Prefab, Texture, or even a Scene), then in the Inspector view at the very bottom click on the dropdown menu, then click 'New...' (or click the existing Asset Bundle name).

Assigning the same bundle name to multiple assets will pack them together in the same Asset Bundle. It's advised to pack Scenes separately from the rest of the assets.

Also, you don't have to assign an Asset Bundle name to every asset. Typically you only need to assign the bundle name to the main prefab or asset, the rest of the dependencies will be included automatically.

Building Asset Bundles

To build Asset Bundles, follow the steps below:

  • Create a new folder called Editor (if you do not have any)
  • Create a new script inside the Editor folder, name it BuildAssetBundles then paste the code below inside it:

BuildAssetBundles.cs

using UnityEngine;
using UnityEditor;

public class BuildAssetBundles
{
    [MenuItem("Build/Build AssetBundles")]
    static void BuildAllAssetBundles()
    {
        string outputFolder = "Assets/__Bundles";

        //Check if __Bundles folder exist
        if (!AssetDatabase.IsValidFolder(outputFolder))
        {
            Debug.Log("Folder '__Bundles' does not exist, creating new folder");

            AssetDatabase.CreateFolder("Assets", "__Bundles");
        }

        BuildPipeline.BuildAssetBundles(outputFolder, BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
    }
}

After saving it you'll notice it will add a menu button (Build -> Build AssetBundles). Clicking it will build the Asset Bundles and place them in the "__Bundles" folder.

Loading Asset Bundles

To load the Asset Bundle it first needs to be downloaded using UnityWebRequest and then unpacked using a special function. Generally, there are 2 types of Asset Bundles, those that contain assets and those that contain Scenes.

Loading Assets From The Asset Bundles

The code below downloads Asset Bundle named "fpsplayer" then extracts the Prefab named "FPSPlayer" and instantiates it in the Scene:

        int assetBundleVersion = 1; // Changing this number will force Asset Bundle reload
        string assetBundlePath = "file://" + Application.dataPath + "/__Bundles/" + "fpsplayer"; // Path to Asset Bundle file
        using (UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(assetBundlePath, (uint)assetBundleVersion, 0))
        {
            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.LogError("AssetBundle Error: " + www.error);
                yield return null;
            }
            else
            {
                // Get downloaded Asset Bundle
                AssetBundle assetBundle = UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent(www);
                // Extract Prefab named "FPSPlayer" from the Asset Bundle
                GameObject playerPrefab = assetBundle.LoadAsset("FPSPlayer") as GameObject;
                // Instantiate Player Prefab
                Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
                // Unload Asset Bundle from memory (but do not destroy the existing instance(s))
                assetBundle.Unload(false);
            }
        }

Loading Scenes From The Asset Bundles

Loading Scene from the Asset Bundle is done slightly differently.

The code below will download the Asset Bundle with a Scene and will make it available for load:

        int assetBundleVersion = 1; // Changing this number will force Asset Bundle reload
        string assetBundlePath = "file://" + Application.dataPath + "/__Bundles/" + "testscene"; // Path to Asset Bundle file
        using (UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(assetBundlePath, (uint)assetBundleVersion, 0))
        {
            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.LogError("AssetBundle Error: " + www.error);
                yield return null;
            }
            else
            {
                // Get downloaded Asset Bundle (This will make the Scene available for load)
                AssetBundle assetBundle = UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent(www);
                // Load the Scene extracted from the Asset Bundle
                UnityEngine.SceneManagement.SceneManager.LoadScene("TestScene");
            }
        }
Suggested Articles
Guide to Audio in Unity
Strategies to Protect Unity Games from Piracy
How to Pick the Right Background Music for Your Game in Unity
How to Paint Trees on Terrain in Unity
Choosing the Right Skybox for Your Environment in Unity
Must-Have General-Purpose Assets for Unity
Comparing 2D and 3D Development Environments in Unity