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, audio clips, and more complex, such as Scenes and Prefabs, that can be later loaded into the game.

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 you do not want to include them in the main build.

Exporting Asset Bundles

Exporting Asset Bundles is done in two steps: assigning Asset Bundle names and building them using 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 on 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 “__Bundles” folder.

Loading Asset Bundles

To load the Asset Bundle it first needs to be downloaded using UnityWebRequest 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");
            }
        }

Leave a Reply

Your email address will not be published. Required fields are marked *