Verwendung von Asset-Bundles in Unity

Unity verfügt über viele nützliche Funktionen, eine davon ist die Unterstützung von Asset Bundles.

Was sind Vermögenspakete?

Asset-Bundles sind Dateien, die Spiel-Assets enthalten, von einfachen Assets wie 3D-Modellen, Texturen und Audioclips bis hin zu komplexeren Assets wie Szenen und Prefabs.

Skripte können jedoch nicht in Asset-Bundles eingebunden werden, sondern nur deren Referenzen. Seien Sie daher beim Umbenennen oder Verschieben vorsichtig, da dadurch die Verbindung unterbrochen wird und Sie die Asset-Bundles neu erstellen müssen, damit sie wieder funktionieren.

Wann sollten Asset-Bundles verwendet werden?

Verwenden Sie Asset-Bundles, wenn Ihr Spiel über viele Assets verfügt und deren Einbeziehung in den Build sich auf die anfängliche Downloadzeit auswirkt.

Asset-Bundles exportieren

Der Export von Asset-Bundles erfolgt in zwei Schritten: Asset-Bundle-Namen zuweisen und mit dem Editor script erstellen.

Asset-Bundle-Namen zuweisen

Um den Asset-Bundle-Namen zuzuweisen, wählen Sie das Asset in der Projektansicht aus (dies kann Prefab, Texture oder sogar eine Szene sein), klicken Sie dann in der Inspektoransicht ganz unten auf das Dropdown-Menü und dann auf 'New...' (bzw Klicken Sie auf den Namen des vorhandenen Asset-Bundles).

Wenn Sie mehreren Assets denselben Bundle-Namen zuweisen, werden diese im selben Asset-Bundle zusammengefasst. Es wird empfohlen, Szenen getrennt vom Rest der Assets zu packen.

Außerdem müssen Sie nicht jedem Asset einen Asset-Bundle-Namen zuweisen. Normalerweise müssen Sie nur den Bundle-Namen dem Hauptfertigteil oder -Asset zuweisen, die restlichen Abhängigkeiten werden automatisch einbezogen.

Aufbau von Asset-Bundles

Um Asset-Bundles zu erstellen, führen Sie die folgenden Schritte aus:

  • Erstellen Sie einen neuen Ordner mit dem Namen Editor (falls Sie noch keinen haben)
  • Erstellen ein neues Skript im Editor-Ordner, nennen Sie es „BuildAssetBundles“ und fügen Sie dann den folgenden Code ein:

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

Nach dem Speichern werden Sie feststellen, dass eine Menüschaltfläche hinzugefügt wird (Build -> AssetBundles erstellen). Wenn Sie darauf klicken, werden die Asset-Bundles erstellt und im Ordner "__Bundles" abgelegt.

Laden von Asset-Bundles

Um das Asset Bundle zu laden, muss es zunächst mit UnityWebRequest heruntergeladen und dann mit einer speziellen Funktion entpackt werden. Im Allgemeinen gibt es zwei Arten von Asset-Bundles: solche, die Assets enthalten, und solche, die Szenen enthalten.

Laden von Assets aus den Asset-Bundles

Der folgende Code lädt das Asset-Bundle mit dem Namen "fpsplayer" herunter, extrahiert dann das Prefab mit dem Namen "FPSPlayer" und instanziiert es in der Szene:

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

Laden von Szenen aus den Asset-Bundles

Das Laden der Szene aus dem Asset Bundle erfolgt etwas anders.

Der folgende Code lädt das Asset-Bundle mit einer Szene herunter und stellt es zum Laden bereit:

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