Tipps für ein effektiveres Arbeiten mit der Asset-Datenbank

Die Asset Import Pipeline v2 ist die neue Standard-Asset-Pipeline in Unity. Sie ersetzt die Asset Import Pipeline v1 mit einer neu geschriebenen Asset-Datenbank, die einen schnellen Plattformwechsel ermöglicht. Es legt den Grundstein für skalierbare Asset-Importe mit robuster Abhängigkeitsverfolgung. Lesen Sie weiter, um zu erfahren, wie die Asset-Datenbank funktioniert und entdecken Sie einige zeitsparende Tipps.
Seit der Veröffentlichung von Unity 2019.3 ist die neue Asset Import Pipeline die Standard-Pipeline für neue Projekte. Zusammen mit vielen anderen Verbesserungen bildet dies die Grundlage für eine zuverlässigere, leistungsfähigere und skalierbarere Asset Import Pipeline. Mit dieser Neufassung wurde die Funktionsweise des Ordners Bibliothek geändert, um neue Arbeitsabläufe zu unterstützen.
Werfen wir einen Blick unter die Haube auf eine Reihe von Situationen, die Ihnen begegnen können, und wie Sie diese effizient bewältigen können. Sie lernen, wie Sie einige der Engpässe, die Sie Zeit und Projektleistung kosten, erkennen und beheben können.
Die Tipps, die Sie hier finden, gelten für Unity 2019.3 und spätere Versionen. Denken Sie daran: Wenn Ihr Projekt über das Prototyping hinaus in Produktion ist, empfehlen wir Ihnen für maximale Stabilität die neueste Long-Term Support (LTS) Version von Unity, Unity 2019 LTS.
Lassen Sie uns zunächst über einige der Dinge sprechen, die passieren, wenn Sie ein neues Projekt erstellen oder ein Projekt öffnen, in dem Ihre Asset-Bibliothek noch nicht vorhanden ist.
Wenn Sie sich die Datei Editor.log ansehen, werden Sie eine Menge Zeilen bemerken, die wie folgt aussehen:
- Importieren beginnen ...
- Erledigt Importieren ...
Auf diese Weise hinterlässt die Asset Import Pipeline eine Spur ihrer Operationen, so dass diese zu einem späteren Zeitpunkt überprüft werden können.
Sie können diese Informationen nutzen, um eine bestimmte Art von Engpässen zu ermitteln, nämlich die Asset-Importzeiten.
Wenn Sie sich die Ausgabe der einzelnen Zeilen ansehen, können Sie die folgenden Daten extrahieren:
- Asset-Pfad
- Dauer des Imports
- Dateierweiterung
Wenn wir diese Daten analysieren, können wir sie nach der Erweiterung kategorisieren. Sobald Sie wissen, welcher Importeur welches Asset importiert hat, können Sie diese Daten in einem Tortendiagramm zusammenfassen, das Ihnen zeigt, welche Arten von Assets am längsten für den Import brauchen. Zum Beispiel:

Diese Daten können Ihnen ein klareres Bild davon vermitteln, wo die Engpässe für Ihr Projekt liegen.
In diesem Beispiel sind Texturen, Modelle und Prefabs die größten Zeitfresser. Das ist ein guter Ausgangspunkt, um zu untersuchen, welche Assets optimiert werden können.
Laden Sie dieses SimpleEditorLogParser-Beispielprojekt herunter und verwenden Sie es als Basis für Ihren eigenen Parser.
Wenn Sie sehen können, welche Asset-Kategorie am längsten für den Import braucht, können Sie planen, wohin Sie Ihre Optimierungsbemühungen lenken sollten. Wenn der Texturimport die Kategorie ist, die am längsten dauert, dann untersuchen Sie die Texturen, deren Import am längsten dauert, und überlegen Sie, ob Sie Texturen, die nicht im endgültigen Build landen sollen, entfernen.
Dies beschleunigt nicht nur Ihre Importzeiten, sondern verbessert auch die Leistung Ihrer Continuous Integration Pipeline, wenn Sie saubere nächtliche Builds oder Ähnliches durchführen.
Es ist wichtig, dass Sie Ihre Projekte schnell öffnen können. Die Minuten, die Sie brauchen, um den Editor neu zu starten oder verschiedene Projekte zu öffnen, können sich zu wertvoller verlorener Zeit summieren.
Je komplexer ein Projekt wird und je mehr Funktionen es enthält, desto länger dauert es, es zu öffnen. Das kann an einer Vielzahl von Faktoren liegen, und vor Unity 2019.3 gab es keine Möglichkeit, den Profiler zu starten, während der Editor gestartet wurde.
Zu den verschiedenen Befehlszeilenargumenten, die Sie beim Öffnen von Unity angeben können, gehört das Befehlszeilenargument -profiler-enable , mit dem Sie den Editor beim Start profilieren können.
Dieser Befehl weist den Editor an, mit der Aufzeichnung von Profildaten für den ersten Frame der Anwendung zu beginnen, d.h. für den gesamten Code, der ausgeführt wird, bis der Editor sichtbar ist. Mit diesem Argument können Sie sehen, was während des Starts passiert und was Zeit braucht. Sie können sehen, ob es sich um ein System in Unity, ein Paket aus dem Asset Store oder um Code speziell für Ihr Projekt handelt. Dies kann Ihnen helfen, herauszufinden, was Sie als nächstes tun sollten.

In dieser Aufnahme sehen Sie, dass das Öffnen dieses speziellen Projekts ca. 50 Sekunden dauert.
Auf den ersten Blick scheint es 43 Sekunden zu dauern, die AssetDatabase zu laden. Bei näherer Betrachtung wird deutlich, dass 14 s für Aufrufe von OnPostProcessAllAssets verwendet werden. Weiter unten summiert sich der Code, der während RegisterScriptsAndTryLoadingExistingUserAssemblies ausgeführt wird, auf 10 s. Davon entfallen 5,7 s auf das Laden der Domäne, was durch Aufrufe von Skripts mit dem Attribut [InitializeOnLoad] weiter verlangsamt wird.
Anhand dieser Startdaten können Sie Leistungsengpässe aufspüren und feststellen, ob der Code in Ihrem Projekt oder in Unity selbst liegt.
Der Bibliotheksordner kann jetzt mehrere Importergebnisse für dasselbe Asset enthalten, so dass Projekte, die die neue Asset-Import-Pipeline verwenden, keine "einfache" GUID (Global Unique Identifier) mehr haben, die dem Ordner im Bibliotheksordner zugeordnet ist.
Die Dateien im Bibliotheksordner basieren auf dem Hash ihres Inhalts sowie einer Reihe von statischen und dynamischen Abhängigkeiten. Dies ermöglicht Unity Funktionen wie den schnellen Plattformwechsel, die Entduplizierung von Assets und das Überspringen eines Imports, wenn der Hash eines Assets bereits im Bibliotheksordner vorhanden ist.
Das bedeutet also, dass es nicht mehr trivial ist, Importergebnisse im Ordner Bibliothek zu finden. Hier ist ein Beispiel, das Ihnen zeigt, wo Sie das Importergebnis von "Assets/Prefabs/MyPrefab.prefab" finden können:
public class LibraryPathsForAsset
{
[MenuItem("AssetDatabase/OutputLibraryPathsForAsset")]
public static void OutputLibraryPathsForAsset()
{
var assetPath = "Assets/Prefabs/MyPrefab.prefab";
StringBuilder assetPathInfo = new StringBuilder();
var guidString = AssetDatabase.AssetPathToGUID(assetPath);
//The ArtifactKey is needed here as there are plans to
//allow importing for different platforms without switching
//platform, thus ArtifactKeys will be parametrized in the future
var artifactKey = new ArtifactKey(new GUID(guidString));
var artifactID = AssetDatabaseExperimental.LookupArtifact(artifactKey);
//Its possible for an Asset to have multiple import results,
//if, for example, Sub-assets are present, so we need to iterate
//over all the artifacts paths
AssetDatabaseExperimental.GetArtifactPaths(artifactID, out var paths);
assetPathInfo.Append($"Files associated with {assetPath}");
assetPathInfo.AppendLine();
foreach (var curVirtualPath in paths)
{
//The virtual path redirects somewhere, so we get the
//actual path on disk (or on the in memory database, accordingly)
var curPath = Path.GetFullPath(curVirtualPath);
assetPathInfo.Append("\t" + curPath);
assetPathInfo.AppendLine();
}
Debug.Log("Path info for asset:\n"+assetPathInfo.ToString());
}
}
Hier sind zwei Gists für verschiedene Versionen von Unity:
Die Beispiele unterscheiden sich, da mit der Weiterentwicklung der Asset Import Pipeline eine Reihe von APIs aus dem Experimental-Namensraum in den AssetDatabase-Namensraum verschoben wurde.
Oft möchten Sie vielleicht ein bestimmtes Asset in Ihrem Projekt finden und etwas mit dem Ergebnis machen. Vielleicht möchten Sie dies sogar mehrmals tun, wenn Sie den Editor-Code ausführen.
Wenn Sie AssetDatabase.FindAssets aufrufen, wird das gesamte Projekt nach der von Ihnen eingegebenen Abfrage durchsucht. Wenn die Projekte größer werden, kann dies zu einem Leistungsengpass werden, da die Zeit für die Suche in Projekten unterschiedlicher Größe linear ansteigt.

Je mehr Assets ein Projekt hat, desto länger dauert es erwartungsgemäß, sie zu durchsuchen. Glücklicherweise bleibt die Zeit, um jeden Vermögenswert zu finden, im Laufe der Zeit relativ konstant.

Sie sehen, wenn Ihr Projekt Hunderttausende von Assets umfasst, kann die Suche nach Assets die Entwicklung spürbar verlangsamen. Bei 200.000 Assets gibt es bereits eine Verzögerung von 200 ms für eine einfache Suchanfrage.
Die Verwendung des Brute-Force-Ansatzes führt zu diesem gängigen Nutzungsmuster:
string[] assets = AssetDatabase.FindAssets ("t:texture2D");
if(assets.Length > 0)
{
string path = AssetDatabase.GUIDToAssetPath (guids[0]);
if (!string.IsNullOrEmpty (path))
{
Texture tex = AssetDatabase.LoadAssetAtPath<Texture>(path);
//Do something with this texture
}
}Im Wesentlichen durchläuft dieser Code das gesamte Projekt, um eine Textur zu finden und dann etwas mit ihr zu tun.
Die AssetDatabase bietet eine Möglichkeit, den Pfad eines Assets anhand der GUID zu suchen. Sie können sich das so vorstellen, dass Sie in einem Dictionary nach einem Schlüssel suchen, anstatt ein Array nach einer Übereinstimmung zu durchlaufen.
Der Vorteil dieses Ansatzes gegenüber Brute-Force ist, dass die AssetDatabase nicht das gesamte Projekt durchsuchen muss, um das Asset zu finden. Es kann einfach die GUID als Datenbankindex verwenden und diesem Pfad folgen, um das Asset in den Speicher zu laden.
Sie finden die GUID zum Beispiel in der entsprechenden .meta-Datei eines Assets:
fileFormatVersion: 2
guid: 9fc0d4010bbf28b4594072e72b8655ab
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
In diesem Fall lautet die GUID für dieses Asset 9fc0d4010bbf28b4594072e72b8655ab.
Mit diesen Informationen können Sie Folgendes tun:
var path = AssetDatabase.GUIDToAssetPath("9fc0d4010bbf28b4594072e72b8655ab");
var asset = AssetDatabase.LoadAssetAtPath<Texture>(path);
Jetzt ist Ihr Asset bereit für die Verwendung.
Nebenbei bemerkt: Wenn Sie die Suche im Editor beschleunigen möchten, sollten Sie sich auch die folgenden Tools ansehen:
Quick Search Package, mit dem Sie mehrere Bereiche von Unity durchsuchen können.
TypeCache, um nach Scripts zu suchen, die von einem Ihnen bekannten Typ abgeleitet sind.
Normalerweise ist die GUID eines Assets konstant.
In bestimmten Situationen werden jedoch ein Asset und seine .meta-Datei dupliziert, was zu einem Konflikt führt, den die AssetDatabase auf folgende Weise auflöst:
Wenn Sie einen Ordner innerhalb eines Projekts an eine andere Stelle desselben Projekts duplizieren
Mehrfaches Importieren eines Asset Store-Pakets oder mehrfaches Kopieren eines Ordners aus einem anderen Projekt in Ihr Projekt
Wenn AssetDatabase.Refresh ausgeführt wird, müssen viele Systeme zusammenarbeiten, um Ihr Projekt in einem gültigen Zustand zu präsentieren. In meinem Vortrag auf der Unite Copenhagen habe ich die verschiedenen Schritte erläutert, die beim Aufrufen von Refresh ablaufen.
Bestimmte Rückrufe, die während eines Refreshs ausgeführt werden, interagieren mit Code. Dies kann sich darauf auswirken, wie lange es dauert, bis der Aktualisierungsvorgang abgeschlossen ist.
Je mehr Code während eines Domain-Reloads ausgeführt wird, desto langsamer wird Ihr Editor. Um bei der Iteration von Code im Fluss zu bleiben, sollten Sie genau überlegen, wann der Code ausgeführt werden soll und ob er auf einen späteren Zeitpunkt im Projekt verschoben werden kann.
Bei einem Domain Reload wird Ihr Code ausgeführt, wenn er eine der folgenden Methoden enthält:
1. Erwachen
2. OnEnable
3. OnValidate
Ihr Code in diesen Methoden sollte idealerweise sehr schnell sein oder zu einem anderen Zeitpunkt ausgeführt werden (z.B. nicht während eines Refreshs). Der Grund dafür ist, dass diese Rückrufe Ihnen dabei helfen sollen, bestimmte Zustände wiederherzustellen. Da es jedoch keine Beschränkungen dafür gibt, was innerhalb dieser Aufrufe getan werden kann, verlangsamt jeder Code, der nicht skalierbar ist (d.h. alles, was das gesamte Projekt durchläuft), Ihre Iterationsgeschwindigkeit für Skripte, während der Editor geöffnet ist.
Ein anderer Ansatz ist die Verwendung von EditorApplication.delayCall, bei dem Ihr Code beim nächsten Editor-Tick ausgeführt wird, nachdem die AssetDatabase die Gelegenheit hatte, alle Änderungen auf der Festplatte zu erkennen und zu importieren.
Verfolgen Sie diesen Thread in den Unity-Foren, um über Neuigkeiten zu Verbesserungen in diesem Bereich auf dem Laufenden zu bleiben.
Ich hoffe, Sie haben diese Tipps nützlich gefunden. Lassen Sie uns wissen, was Sie sonst noch gerne über die Asset Import Pipeline wissen möchten oder welche Probleme Sie haben. Wir arbeiten aktiv an der Verbesserung der Asset-Import-Pipeline und möchten, dass Ihre Iteration so schnell wie möglich erfolgt, damit Sie produktiver mit dem Editor arbeiten und Assets und/oder Skripts ändern können.
