Der Umgang mit externen Dateien in Unity spielt sowohl während der Spieleentwicklung als auch im fertigen Spiel eine wichtige Rolle. Bilder, Audiodateien, Konfigurationen und Textdateien können aus unterschiedlichen Quellen stammen. Nicht jede Datei muss bereits beim Erstellen des Projekts fest eingebunden sein.
Unity unterscheidet zwischen Dateien, die der Editor als Assets importiert, und Daten, auf die ein Spiel während der Laufzeit zugreift. Diese Unterscheidung beeinflusst, welche Funktionen du verwenden kannst, wo Dateien gespeichert liegen und ob sie nach dem Erstellen eines Builds noch verändert werden dürfen.
Besonders bei Spielständen, benutzerdefinierten Einstellungen, zusätzlichen Inhalten oder externen Konfigurationsdateien benötigst du einen geeigneten Umgang mit Dateipfaden und Speicherorten.
Was sind externe Dateien in Unity?
Als externe Dateien lassen sich Daten bezeichnen, die außerhalb der unmittelbar im Spiel verwendeten Unity-Objekte vorliegen. Dazu gehören beispielsweise Textdateien, Bilder, Audiodateien, JSON-Dateien oder gespeicherte Spielstände.
Entscheidend ist, wie Unity auf diese Daten zugreift. Eine Bilddatei im Assets-Ordner wird normalerweise vom Unity Editor importiert und als Textur verarbeitet. Eine Bilddatei, die ein Spieler erst nach der Installation auswählt, benötigt dagegen eine eigene Ladefunktion zur Laufzeit.
Auch Dateien, die bereits im Projekt liegen, können auf unterschiedliche Weise behandelt werden. Der Speicherort bestimmt häufig, ob Unity die Datei importiert, unverändert in den Build übernimmt oder sie erst über ein Script einliest.
Der Unterschied zwischen Asset-Import und Dateizugriff
Beim gewöhnlichen Asset-Import erkennt Unity Dateien im Assets-Verzeichnis und verarbeitet sie über den zuständigen Importer. Daraus entstehen Ressourcen, die du beispielsweise in Szenen, Prefabs oder Scripts referenzieren kannst.
Beim Dateizugriff zur Laufzeit liest dein Spiel dagegen Daten aus einem erreichbaren Speicherort. Die vollständigen Importfunktionen des Unity Editors stehen dabei nicht automatisch zur Verfügung.
Ein extern geladenes Bild ist deshalb nicht unmittelbar mit einem im Editor importierten Sprite gleichzusetzen. Du musst die Bilddaten zunächst laden, daraus eine Textur erzeugen und bei Bedarf anschließend ein Sprite erstellen.
Die grundlegenden Importwege behandelt der Artikel über die Importfunktion von Unity. Beim Zugriff auf externe Dateien stehen dagegen die Speicherorte, Dateiformate und eigenen Ladefunktionen im Mittelpunkt.
Welche Speicherorte stellt Unity bereit?
Unity stellt verschiedene Pfade zur Verfügung, die du über die Klasse Application abrufen kannst. Dazu gehören insbesondere Application.dataPath, Application.streamingAssetsPath, Application.persistentDataPath und Application.temporaryCachePath.
Diese Pfade erfüllen unterschiedliche Aufgaben. Manche beziehen sich auf die installierten Spieldaten, andere auf Dateien, die dein Spiel selbst speichern oder später erneut laden soll.
Die tatsächlichen Verzeichnisse unterscheiden sich je nach Betriebssystem und Zielplattform. Deshalb solltest du die von Unity bereitgestellten Pfade verwenden, statt feste Verzeichnisnamen vorauszusetzen.
Application.dataPath – Zugriff auf den Datenbereich der Anwendung
Mit Application.dataPath erhältst du einen Pfad zum Datenbereich der Anwendung. Im Unity Editor verweist dieser auf den Assets-Ordner des Projekts.
In einem fertigen Build kann der Pfad dagegen auf einen anderen Speicherort zeigen. Seine genaue Bedeutung hängt von der Plattform ab.
Für eigene Spielstände oder dauerhaft veränderbare Konfigurationsdateien solltest du diesen Pfad normalerweise nicht verwenden. Installationsverzeichnisse können schreibgeschützt sein oder sich bei Updates verändern.
Für solche Daten ist Application.persistentDataPath die geeignetere Grundlage.
Application.persistentDataPath – Dateien dauerhaft speichern
Der Pfad Application.persistentDataPath bezeichnet einen Speicherort für Daten, die dein Spiel über mehrere Starts hinweg behalten soll.
Dazu gehören beispielsweise Spielstände, Einstellungen, freigeschaltete Inhalte oder vom Spieler erstellte Daten.
Unity stellt für unterstützte Plattformen einen geeigneten Speicherpfad bereit. Dadurch musst du nicht selbst entscheiden, in welchem Benutzerverzeichnis die Daten abgelegt werden sollen.
Die gespeicherten Dateien bleiben normalerweise auch nach dem Beenden des Spiels bestehen. Ob sie bei einer Deinstallation oder bestimmten Plattformaktionen erhalten bleiben, hängt allerdings von der jeweiligen Umgebung ab.
Eine Textdatei mit C# speichern
Für einfache Textdateien kannst du die Klassen aus System.IO verwenden. Das folgende Beispiel speichert einen Text innerhalb des persistenten Datenverzeichnisses:
using System.IO;
using UnityEngine;
public class TextFileSaver : MonoBehaviour
{
public void SaveText()
{
string path = Path.Combine(
Application.persistentDataPath,
"example.txt"
);
string content = "Meine erste externe Datei";
File.WriteAllText(path, content);
Debug.Log("Datei gespeichert: " + path);
}
}
Path.Combine() setzt den Speicherpfad und den Dateinamen zusammen. Dadurch vermeidest du, die Verzeichnistrennzeichen für unterschiedliche Betriebssysteme selbst festlegen zu müssen.
Mit File.WriteAllText() schreibt das Script den angegebenen Text in die Datei. Existiert sie bereits, überschreibt die Methode ihren bisherigen Inhalt.
Bei produktiven Anwendungen solltest du mögliche Schreibfehler abfangen. Dazu gehören beispielsweise fehlende Berechtigungen oder ein nicht verfügbarer Speicherort.
Eine gespeicherte Textdatei wieder einlesen
Mit File.ReadAllText() kannst du den Inhalt einer vorhandenen Textdatei auslesen. Vorher solltest du prüfen, ob die Datei tatsächlich existiert.
using System.IO;
using UnityEngine;
public class TextFileLoader : MonoBehaviour
{
public void LoadText()
{
string path = Path.Combine(
Application.persistentDataPath,
"example.txt"
);
if (!File.Exists(path))
{
Debug.Log("Datei nicht gefunden.");
return;
}
string content = File.ReadAllText(path);
Debug.Log(content);
}
}
Das Script prüft mit File.Exists(), ob die Datei vorhanden ist. Anschließend liest es den Text ein und gibt ihn in der Console aus.
Dieses Verfahren eignet sich für kleinere Textdateien. Bei sehr großen Dateien oder häufigen Dateizugriffen solltest du zusätzlich auf Speicherbedarf und mögliche Blockierungen des Hauptthreads achten.
JSON-Dateien für strukturierte Spieldaten
Das JSON-Format eignet sich für strukturierte Daten, die dein Spiel speichern oder laden soll. Dazu gehören beispielsweise Spielerpositionen, Einstellungen, Inventarinhalte oder andere Spielzustände.
Unity stellt mit JsonUtility eine einfache Möglichkeit bereit, geeignete C#-Datenobjekte in JSON umzuwandeln und anschließend wieder einzulesen.
JsonUtility unterstützt allerdings nicht sämtliche Möglichkeiten allgemeiner JSON-Bibliotheken. Die Datenstruktur muss zu den Serialisierungsregeln von Unity passen.
Spielstände als JSON speichern
Das folgende Beispiel speichert einen einfachen Spielstand mit Levelnummer und Punktestand.
using System;
using System.IO;
using UnityEngine;
[Serializable]
public class SaveData
{
public int level = 1;
public int score = 0;
}
public class SaveGame : MonoBehaviour
{
public void Save()
{
SaveData data = new SaveData
{
level = 3,
score = 250
};
string json = JsonUtility.ToJson(
data,
true
);
string path = Path.Combine(
Application.persistentDataPath,
"savegame.json"
);
File.WriteAllText(path, json);
Debug.Log("Spielstand gespeichert.");
}
}
Die Klasse SaveData enthält die Werte, die gespeichert werden sollen. Das Attribut [Serializable] ermöglicht die entsprechende Verarbeitung durch Unity.
JsonUtility.ToJson() wandelt die Daten in eine JSON-Zeichenfolge um. Mit dem zweiten Parameter true wird der Text übersichtlich formatiert.
Anschließend schreibt das Script die JSON-Daten in eine Datei innerhalb von persistentDataPath.
JSON-Spielstände wieder laden
Gespeicherte JSON-Daten kannst du mit JsonUtility.FromJson() wieder in ein passendes Datenobjekt umwandeln.
using System.IO;
using UnityEngine;
public class LoadGame : MonoBehaviour
{
public void Load()
{
string path = Path.Combine(
Application.persistentDataPath,
"savegame.json"
);
if (!File.Exists(path))
{
Debug.Log("Kein Spielstand vorhanden.");
return;
}
string json = File.ReadAllText(path);
SaveData data =
JsonUtility.FromJson<SaveData>(json);
Debug.Log("Level: " + data.level);
Debug.Log("Punkte: " + data.score);
}
}
Das Beispiel verwendet die zuvor definierte Klasse SaveData. Beide Scripts müssen deshalb im selben Projekt vorhanden sein.
Bei einer vollständigen Speicherfunktion solltest du zusätzlich prüfen, ob die Datei gültige Daten enthält. Fehlerhafte oder unvollständige Spielstände dürfen nicht dazu führen, dass das gesamte Spiel unkontrolliert abbricht.
StreamingAssets – Dateien unverändert in den Build übernehmen
Der Ordner StreamingAssets ist für Dateien vorgesehen, die Unity beim Erstellen des Builds weitgehend unverändert übernehmen soll.
Du kannst ihn unter Assets/StreamingAssets anlegen. Die enthaltenen Dateien stehen anschließend über Application.streamingAssetsPath zur Verfügung.
StreamingAssets eignet sich beispielsweise für bestimmte Konfigurationsdateien, zusätzliche Datensammlungen oder Medien, die nicht über den gewöhnlichen Asset-Import verarbeitet werden sollen.
Der Ordner ist jedoch kein allgemeiner Speicherort für veränderbare Spielstände. In einem fertigen Build können seine Inhalte schreibgeschützt oder innerhalb eines Pakets gespeichert sein.
Dateien aus StreamingAssets laden
Auf manchen Plattformen kannst du Dateien aus StreamingAssets über gewöhnliche Dateifunktionen lesen. Das funktioniert jedoch nicht überall.
Insbesondere unter Android können StreamingAssets innerhalb des Anwendungspakets liegen. Dort ist ein direkter Zugriff über File.ReadAllText() nicht in derselben Weise möglich wie bei einer gewöhnlichen Datei auf dem PC.
Für einen plattformübergreifenden Lesezugriff kannst du UnityWebRequest verwenden. Die genaue Behandlung des Pfads hängt dabei von der Plattform ab.
Eine Textdatei mit UnityWebRequest laden
Das folgende Beispiel lädt eine Textdatei aus dem StreamingAssets-Ordner. Auf Plattformen, auf denen der Pfad bereits als URL bereitsteht, verwendet es diesen direkt. Andernfalls erzeugt es eine lokale Datei-URL.
using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
public class StreamingTextLoader : MonoBehaviour
{
private IEnumerator Start()
{
string path = Path.Combine(
Application.streamingAssetsPath,
"example.txt"
);
string url = path;
if (!path.Contains("://"))
{
url = new Uri(path).AbsoluteUri;
}
using (UnityWebRequest request =
UnityWebRequest.Get(url))
{
yield return request.SendWebRequest();
if (request.result !=
UnityWebRequest.Result.Success)
{
Debug.LogError(request.error);
yield break;
}
string content =
request.downloadHandler.text;
Debug.Log(content);
}
}
}
Das Script erwartet eine Datei namens example.txt im StreamingAssets-Ordner. Die Coroutine wartet, bis die Anfrage abgeschlossen ist, und liest anschließend den Text aus.
Bei einer Verwendung auf unterschiedlichen Zielplattformen solltest du den Zugriff jeweils im fertigen Build testen. Besonders WebGL und mobile Plattformen können zusätzliche Einschränkungen besitzen.
Resources – Dateien über das Unity-Ressourcensystem laden
Eine weitere Möglichkeit ist der Resources-Ordner. Dateien in einem entsprechend benannten Verzeichnis können über die Unity-API Resources.Load() geladen werden.
Anders als bei StreamingAssets verarbeitet Unity die unterstützten Dateien im Resources-Ordner als gewöhnliche Assets.
Du kannst beispielsweise eine Textdatei als TextAsset laden oder einen importierten Audio Clip über seinen Ressourcenpfad abrufen.
Für größere Projekte solltest du den Resources-Ordner bewusst einsetzen. Ressourcen in solchen Ordnern können den Buildumfang beeinflussen, auch wenn sie nicht direkt in einer Szene referenziert werden.
Eine Textdatei mit Resources.Load einlesen
Das folgende Beispiel lädt eine Textdatei aus einem Resources-Ordner:
using UnityEngine;
public class ResourceTextLoader : MonoBehaviour
{
private void Start()
{
TextAsset textFile =
Resources.Load<TextAsset>(
"Data/example"
);
if (textFile == null)
{
Debug.LogError(
"Textdatei nicht gefunden."
);
return;
}
Debug.Log(textFile.text);
}
}
Das Script erwartet beispielsweise die Datei Assets/Resources/Data/example.txt.
Beim Aufruf von Resources.Load() gibst du den Pfad relativ zum Resources-Ordner an. Die Dateiendung wird dabei nicht mitgeschrieben.
Die Datei ist hier bereits Teil des Unity-Projekts und wird über das Ressourcensystem geladen. Es handelt sich deshalb nicht um den freien Zugriff auf eine beliebige externe Datei.
Addressables für die Verwaltung zusätzlicher Inhalte
Für größere Projekte bietet Unity das Addressables-System an. Es ermöglicht die Verwaltung und das asynchrone Laden entsprechend vorbereiteter Assets.
Addressables kann Ressourcen lokal bereitstellen oder über geeignete Konfigurationen aus entfernten Quellen laden.
Das System eignet sich beispielsweise für umfangreiche Spiele mit vielen Ressourcen, zusätzlichen Inhalten oder einer gezielten Speicherverwaltung.
Addressables ersetzt jedoch nicht automatisch einen allgemeinen Dateidialog. Die betreffenden Assets müssen zunächst entsprechend vorbereitet und in das System eingebunden werden.
Externe Bilder zur Laufzeit laden
Ein Spiel kann auch Bilder laden, die erst nach der Veröffentlichung verfügbar sind. Dazu musst du die Bilddaten einlesen und daraus eine Unity-Textur erzeugen.
Für unterstützte Bilddaten kannst du beispielsweise Texture2D.LoadImage() verwenden. Diese Methode dekodiert Bilddaten und übernimmt sie in eine Texture2D.
Die Methode eignet sich insbesondere für PNG- und JPG-Daten. Andere Formate benötigen gegebenenfalls zusätzliche Verarbeitung.
Ein PNG-Bild aus persistentDataPath laden
Das folgende Beispiel lädt eine PNG-Datei und weist die daraus erzeugte Textur einem SpriteRenderer zu:
using System.IO;
using UnityEngine;
public class ExternalImageLoader : MonoBehaviour
{
[SerializeField] private SpriteRenderer targetRenderer;
public void LoadImage()
{
string path = Path.Combine(
Application.persistentDataPath,
"picture.png"
);
if (!File.Exists(path))
{
Debug.LogError("Bild nicht gefunden.");
return;
}
byte[] imageData = File.ReadAllBytes(path);
Texture2D texture = new Texture2D(2, 2);
if (!texture.LoadImage(imageData))
{
Destroy(texture);
Debug.LogError("Bild konnte nicht geladen werden.");
return;
}
Sprite sprite = Sprite.Create(
texture,
new Rect(
0,
0,
texture.width,
texture.height
),
new Vector2(0.5f, 0.5f)
);
targetRenderer.sprite = sprite;
}
}
Das Script liest die Bilddatei als Byte-Array ein. Anschließend erstellt es eine Texture2D und dekodiert die Bilddaten mit LoadImage().
Über Sprite.Create() entsteht ein Sprite, das der SpriteRenderer anzeigen kann. Im Inspector musst du dem Feld Target Renderer den gewünschten SpriteRenderer zuweisen.
Bei einer wiederholten Verwendung solltest du zusätzlich die Lebensdauer der erzeugten Texturen und Sprites verwalten. Andernfalls können sich ungenutzte Ressourcen im Speicher ansammeln.
Externe Audiodateien laden
Auch Musik und Soundeffekte können zur Laufzeit aus externen Quellen geladen werden. Dafür stellt Unity unter anderem UnityWebRequestMultimedia.GetAudioClip() bereit.
Die Methode lädt Audiodaten und stellt sie bei erfolgreicher Verarbeitung als Audio Clip bereit. Welche Formate unterstützt werden, hängt von der Plattform und dem angegebenen Audiotyp ab.
Ein extern geladener Audio Clip kann anschließend einer Audio Source zugewiesen und abgespielt werden.
Eine externe WAV-Datei abspielen
Das folgende Beispiel lädt eine WAV-Datei aus dem persistenten Datenverzeichnis und spielt sie über eine Audio Source ab:
using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
public class ExternalAudioLoader : MonoBehaviour
{
[SerializeField] private AudioSource audioSource;
private IEnumerator Start()
{
if (audioSource == null)
{
yield break;
}
string path = Path.Combine(
Application.persistentDataPath,
"music.wav"
);
if (!File.Exists(path))
{
Debug.LogError("Audiodatei nicht gefunden.");
yield break;
}
string url = new Uri(path).AbsoluteUri;
using (UnityWebRequest request =
UnityWebRequestMultimedia.GetAudioClip(
url,
AudioType.WAV
))
{
yield return request.SendWebRequest();
if (request.result !=
UnityWebRequest.Result.Success)
{
Debug.LogError(request.error);
yield break;
}
AudioClip clip =
DownloadHandlerAudioClip.GetContent(
request
);
audioSource.clip = clip;
audioSource.Play();
}
}
}
Das Script prüft zunächst, ob die Datei vorhanden ist. Anschließend erzeugt es eine lokale Datei-URL und lädt die Audiodaten über UnityWebRequest.
Nach erfolgreichem Laden erhält die Audio Source den erzeugten Audio Clip und beginnt mit der Wiedergabe.
Das Beispiel eignet sich für Plattformen mit entsprechendem lokalem Dateizugriff. Auf WebGL oder anderen eingeschränkten Plattformen benötigst du möglicherweise einen anderen Speicher- beziehungsweise Ladeweg.
Dateien aus dem Internet herunterladen
Unity kann externe Daten auch über HTTP- oder HTTPS-Verbindungen laden. Dafür steht die Klasse UnityWebRequest zur Verfügung.
Damit kannst du beispielsweise Konfigurationsdateien, Bilder oder andere unterstützte Daten von einem Server abrufen.
Bei Dateien aus dem Internet solltest du beachten, dass der Download fehlschlagen kann. Ursachen sind beispielsweise fehlende Netzwerkverbindungen, Serverfehler oder ungültige Adressen.
Auch die Größe der heruntergeladenen Datei ist wichtig. Besonders bei großen Dateien kann eine geeignete Zwischenspeicherung sinnvoll sein, damit sie nicht bei jedem Spielstart erneut übertragen werden müssen.
Externe Dateien und Benutzerberechtigungen
Der Zugriff auf Dateien hängt von der Zielplattform ab. Auf einem Desktop-System stehen häufig andere Möglichkeiten zur Verfügung als auf einem Smartphone oder innerhalb eines Webbrowsers.
Bei mobilen Betriebssystemen können zusätzliche Berechtigungen erforderlich sein, wenn eine Anwendung auf bestimmte Dateien außerhalb ihres eigenen Speicherbereichs zugreifen soll.
Auch WebGL-Anwendungen besitzen keinen uneingeschränkten Zugriff auf das Dateisystem des Computers. Sie laufen innerhalb der Sicherheitsbeschränkungen des Browsers.
Deshalb solltest du frühzeitig festlegen, auf welchen Plattformen dein Spiel externe Dateien laden oder speichern können soll.
Dateidialoge für vom Spieler ausgewählte Dateien
Manche Spiele oder Anwendungen sollen dem Benutzer ermöglichen, selbst eine Datei auszuwählen. Dazu gehören beispielsweise eigene Bilder, Musikstücke oder Konfigurationsdateien.
Unity stellt in seinem Editor entsprechende Dateidialoge bereit. Diese gehören jedoch zum Editor-System und stehen in einem fertigen Spiel nicht automatisch zur Verfügung.
Für einen Dateiauswahldialog zur Laufzeit benötigst du eine geeignete plattformspezifische Lösung oder ein entsprechendes Plugin.
Auf WebGL erfolgt die Dateiauswahl üblicherweise über die Möglichkeiten des Browsers. Auf Desktop- und Mobilplattformen können andere Verfahren erforderlich sein.
Dateien auf ihre Gültigkeit überprüfen
Wenn dein Spiel externe Dateien verarbeitet, solltest du nicht davon ausgehen, dass jede Datei korrekt aufgebaut ist.
Eine JSON-Datei kann ungültige Daten enthalten. Eine Bilddatei kann beschädigt sein oder ein unerwartetes Format besitzen. Auch eine Audiodatei muss nicht zwangsläufig von der verwendeten Ladefunktion unterstützt werden.
Deshalb solltest du Dateizugriffe mit geeigneten Prüfungen absichern. Dazu gehören das Kontrollieren vorhandener Dateien, die Begrenzung akzeptierter Dateigrößen und die Behandlung möglicher Fehler.
Bei Dateien aus unbekannten Quellen ist besondere Vorsicht sinnvoll. Externe Inhalte sollten nicht ungeprüft als vertrauenswürdige Daten behandelt werden.
Dateipfade plattformunabhängig zusammensetzen
Unterschiedliche Betriebssysteme verwenden teilweise verschiedene Regeln für Dateipfade. Deshalb solltest du Verzeichnisse und Dateinamen nicht unnötig durch fest eingetragene Trennzeichen verbinden.
Mit Path.Combine() stellt C# eine Funktion bereit, die Pfadbestandteile passend zusammensetzt.
string path = Path.Combine(
Application.persistentDataPath,
"Saves",
"savegame.json"
);
Das Beispiel erzeugt einen Pfad zu einer Datei innerhalb eines Unterordners namens Saves.
Bevor du dort eine Datei speicherst, musst du sicherstellen, dass der Unterordner existiert. Falls erforderlich, kannst du ihn mit Directory.CreateDirectory() anlegen.
Dateien sicher speichern und überschreiben
Beim Speichern wichtiger Daten solltest du berücksichtigen, dass ein Schreibvorgang unterbrochen werden kann. Das kann beispielsweise durch einen Programmabsturz oder einen unerwarteten Systemfehler passieren.
Wenn ein bestehender Spielstand direkt überschrieben wird, besteht bei einem Fehler das Risiko einer beschädigten Datei.
Eine mögliche Gegenmaßnahme besteht darin, Daten zunächst in eine temporäre Datei zu schreiben und sie erst nach erfolgreichem Abschluss an die Stelle des bisherigen Spielstands zu setzen.
Für besonders wichtige Spielstände können zusätzliche Sicherungskopien und eine Prüfung der gespeicherten Daten sinnvoll sein. Die konkrete Umsetzung muss zur jeweiligen Zielplattform passen.
Temporäre Dateien und Cache-Daten
Nicht jede Datei muss dauerhaft gespeichert bleiben. Für vorübergehende Daten stellt Unity Application.temporaryCachePath bereit.
Dieser Speicherort eignet sich beispielsweise für temporäre Downloads oder Daten, die dein Spiel bei Bedarf erneut erzeugen kann.
Du solltest allerdings nicht davon ausgehen, dass Dateien dort dauerhaft erhalten bleiben. Das Betriebssystem kann temporäre Daten unter bestimmten Bedingungen entfernen.
Spielstände und wichtige Benutzereinstellungen gehören deshalb normalerweise nicht in das temporäre Cache-Verzeichnis.
Externe Dateien und die Performance
Das Laden und Speichern von Dateien benötigt Zeit. Besonders große Dateien können die Reaktionsfähigkeit eines Spiels beeinträchtigen, wenn ihre Verarbeitung den Hauptthread blockiert.
Für umfangreichere Ladevorgänge können asynchrone Verfahren sinnvoll sein. UnityWebRequest ermöglicht beispielsweise das Laden von Daten, ohne den gesamten Download als blockierenden Vorgang auf dem Hauptthread auszuführen.
Auch nach dem Laden kann die Verarbeitung zusätzlichen Aufwand verursachen. Das Dekodieren eines großen Bildes oder das Erzeugen einer Textur benötigt beispielsweise Ressourcen.
Bei häufig verwendeten Dateien kann es sinnvoll sein, bereits geladene Daten zwischenzuspeichern, statt sie bei jeder Verwendung erneut einzulesen.
Typische Fehler beim Umgang mit externen Dateien
Probleme entstehen häufig durch ungeeignete Speicherorte, fehlende Dateien oder Unterschiede zwischen dem Unity Editor und dem fertigen Build.
- Datei nicht gefunden: Kontrolliere den vollständigen Pfad und die Schreibweise des Dateinamens.
- Datei lässt sich nicht speichern: Prüfe, ob der gewählte Speicherort beschreibbar ist.
- Funktioniert nur im Editor: Möglicherweise verwendet das Script eine Editor-API oder einen Pfad, der im Build anders aufgebaut ist.
- StreamingAssets funktioniert nicht mit File.ReadAllText: Auf bestimmten Plattformen ist ein anderer Lesezugriff erforderlich.
- JSON kann nicht verarbeitet werden: Prüfe das Format und die verwendete Datenklasse.
- Bild wird nicht angezeigt: Kontrolliere, ob die Bilddaten erfolgreich dekodiert wurden und ein Sprite beziehungsweise eine Textur korrekt zugewiesen ist.
- Audiodatei wird nicht abgespielt: Prüfe Dateiformat, Ladeergebnis und Audio Source.
- Spiel friert beim Laden ein: Große oder häufige synchrone Dateizugriffe können den Hauptthread blockieren.
Für die Fehlersuche solltest du den tatsächlich verwendeten Dateipfad ausgeben und kontrollieren, ob er auf der jeweiligen Plattform erreichbar ist. Anschließend kannst du die Verarbeitung der geladenen Daten untersuchen.
Welche Methode eignet sich für welche Dateien?
Unity bietet verschiedene Wege für den Umgang mit Dateien. Die passende Methode hängt davon ab, ob die Ressource bereits während der Entwicklung bekannt ist oder erst zur Laufzeit entsteht.
- Assets-Ordner: Für Ressourcen, die Unity während der Entwicklung importieren und verarbeiten soll.
- Resources: Für entsprechend vorbereitete Unity-Assets, die du über Resources.Load abrufen möchtest.
- StreamingAssets: Für Dateien, die möglichst unverändert mit dem Build ausgeliefert werden sollen.
- persistentDataPath: Für Spielstände, Einstellungen und andere dauerhaft gespeicherte Benutzerdaten.
- temporaryCachePath: Für vorübergehende Dateien und wiederherstellbare Cache-Daten.
- UnityWebRequest: Für geeignete lokale oder entfernte Datenquellen, insbesondere bei asynchronen Ladevorgängen.
- Addressables: Für die organisierte Bereitstellung und das Laden entsprechend vorbereiteter Assets.
Externe Dateien als Erweiterung des Spiels
Der Zugriff auf externe Dateien eröffnet zusätzliche Möglichkeiten für die Spieleentwicklung. Du kannst Spielstände speichern, Einstellungen dauerhaft verwalten, Inhalte aus Dateien laden oder Spielern die Verwendung eigener Ressourcen ermöglichen.
Entscheidend ist die Trennung zwischen dem Import im Unity Editor und dem Dateizugriff zur Laufzeit. Während der Editor viele Formate automatisch in Unity-Assets umwandelt, benötigt das fertige Spiel passende Lade- und Verarbeitungsfunktionen.
Mit den vorgesehenen Speicherpfaden, geeigneten Dateiformaten und einer zuverlässigen Fehlerbehandlung kannst du externe Daten in dein Spiel integrieren, ohne die Projektstruktur oder die vorhandenen Unity-Assets unnötig zu verändern.
Weitere technische Informationen findest du im Unity-Handbuch zu StreamingAssets.
