ruk·si

⬜️ Unity
Asset Bundles

Updated at 2016-10-30 11:00

Asset bundles allow changing game content run-time. Usually downloaded over the Internet to provide extra prefabs, models, textures, audio clips or scenes, depending on the file extension. If you want to include files with custom binary data, they should have the extension .bytes.

Developer creates an asset bundle from a group of assets.
Developer uploads the asset bundle to a server.
Game client downloads the asset bundle from the server.
Game client loads the asset bundle to memory cache.
Game client can access individual assets from the cache.

AssetBundle names are always lower-case. If you use upper-case, they will be converted.

/ in asset bundle name indicates a folder. This helps working with a lot of bundles with visual tools e.g. environment/desert

Asset bundles can have executable code via assemblies. If you include a C# source file in an asset bundle, it becomes a TextAsset and will not be actual executable code. But you can pre-compile code into a C# assembly using any C# IDE. Note that some mobile platforms don't allow you to send executable code.

  • This works on platforms that don't have Ahead-Of-Time restriction. So allowed on PC/Mac standalone and Mono-on-Android, which both support Just-In-Time compilation.
using UnityEngine;

public class AssetBundleCode : MonoBehaviour
{
    while (!Caching.ready) { yield return null; }
    WWW www = WWW.LoadFromCacheOrDownload("http://example.com/box.unity3d", 1);
    yield return www;
    AssetBundle bundle = www.assetBundle;
    TextAsset txt = bundle.Load("myBinaryAsText", typeof(TextAsset)) as TextAsset;

    var assembly = System.Reflection.Assembly.Load(txt.bytes);
    var type = assembly.GetType("MyClassDerivedFromMonoBehaviour");

    GameObject go = new GameObject();
    go.AddComponent(type);
}

C# class names must match for prefab components. If you include prefabs in the bundle that have script components, those classes themselves are not included in the bundle, prefab only references to them.

  • Path where the script is on build and on load doesn't have to be the same, only the C# namespace and class name must match.
  • The class doesn't have to be exactly the same file content, but must provide similar public interface as the original so deserialization works.
I bundle Avatar prefab with MyPlayerController script attached.
When I load the Avatar asset from the bundle, game client must have a C# class
named MyPlayerController in the project.

Building an asset bundles creates at least 4 files.

// The asset bundle itself, this is frequently the only file you need.
Assets/AssetBundles/test/my_asset_bundle
// Metadata about the asset bundle e.g. included assets list and dependencies.
Assets/AssetBundles/test/my_asset_bundle.manifest
// AssetBundle file for the directory, only one is generated if you create
// all asset bundles in this directory.
Assets/AssetBundles/test/test
// Metadata how asset bundles relate to each other.
Assets/AssetBundles/test/test.manifest

Loading from file system.

using System.IO;
using UnityEngine;

public class Loader : MonoBehaviour
{
    private void Start()
    {
        var assetBundleName = "my_asset_bundle";
        var path = Path.Combine(Application.dataPath, assetBundleName);
        var bundle = AssetBundle.LoadFromFile(path);
        if (bundle == null) {
            Debug.LogError("failed to load AssetBundle");
            return;
        }
        var prefab = bundle.LoadAsset<GameObject>("MyPrefab");
        GameObject.Instantiate(prefab);
    }
}

Sources