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");
}
}