Warum Ordnerstrukturen wichtig sind

Als Berater im Customer Success- Team werde ich oft gefragt: „Haben wir unsere Asset-Bündel richtig zusammengestellt?“ oder eine Variante dieser Frage. Meine Antwort ist immer die gleiche: Das hängt vom Projekt ab. Dann spreche ich mit den Kunden über die Einzelheiten. Obwohl diese Antwort zutreffend ist, liefert sie keine Erkenntnisse, die für zukünftige Projekte hilfreich sind.
Obwohl es sich um ein häufiges Dilemma handelt, fällt es mir schwer, eine allgemeinere Antwort auf die Frage zu finden (trotz unserer bestehenden Richtlinien und Best Practices für adressierbare Elemente). Manche Benutzer wissen nicht, ob die Bundles von Anfang an richtig sind, und meine Zeit beschränkt sich häufig auf die Prüfung von Projekten zur Speicheroptimierung. Dies bedeutet, dass ich nicht für jedes Asset in einem Projekt den beabsichtigten Verwendungszweck angeben kann. Darüber hinaus kann es mit zunehmender Skalierung eines Projekts für eine einzelne Person unmöglich werden, für jeden einzelnen Vermögenswert die gleiche Frage zu beantworten.
Irgendwann wurde mir Folgendes klar: Die Frage nach der Bildung von Vermögensbündeln schränkt die Perspektive für die Suche nach einer allgemeineren Antwort richtig ein. Lassen Sie mich das erklären.
Ein Asset-Bündel belegt zum Laden Speicher. Wenn Assets also zusammen mit anderen Assets gebündelt werden, die nicht gleichzeitig geladen und entladen werden, nutzen Sie den Speicher nicht so optimal, wie Sie könnten. Die Frage, ob sich ein Asset im richtigen Paket befindet oder ob die Pakete die richtigen Assets enthalten, ist daher im Wesentlichen die Frage, ob Sie die richtigen Assets zum richtigen Zeitpunkt laden. Die Frage, wann bestimmte Assets geladen werden sollten, hängt vom beabsichtigten Verwendungszweck dieser Assets ab. Daher lautet die Antwort normalerweise: „Das hängt vom Projekt ab.“ In der Praxis habe ich festgestellt, dass das Erlernen des Verwendungszwecks des Assets Aufschluss darüber gibt, wie die Assets in den Speicher geladen werden und wie sie gebündelt werden sollten.
Der Schlüsselbegriff lautet also „bestimmungsgemäße Verwendung“: Wer weiß, wofür ein Vermögenswert bestimmt ist? Wie kommunizieren Sie diese Absicht allen? Und schließlich: Wann soll dies geschehen?
Meiner Meinung nach gibt es einen Moment, in dem die Antwort auf diese Frage kristallklar ist: bei der Erstellung und Änderung von Assets. Ob es sich um eine bestimmte Textur für einen Charakter, einen globalen Beleuchtungs-Shader oder ein Baumnetz zur Verwendung in mehreren Spielleveln handelt, der Entwickler kennt den Verwendungszweck und ist daher am besten in der Lage, diese Absicht zu kommunizieren. Künstler können diese Absicht kommunizieren, indem sie eine konsistente Dateibenennungskonvention implementieren und Dateien mit demselben Verwendungszweck im selben Ordner gruppieren.
Programmierer und andere Teammitglieder können diese Informationen dann verwenden, um zu entscheiden, wann und ob ein Asset mit anderen Assets gebündelt werden soll, die gleichzeitig geladen werden. Aus diesem Grund muss die beabsichtigte Verwendung eines Assets für die Dauer eines Projekts auf einen Blick klar ersichtlich sein und das Dateiverzeichnis dient allen Teammitgliedern als Quelle der Wahrheit.
In diesem Blogbeitrag werde ich einige Best Practices und häufige Randfälle betrachten, die Ihnen hoffentlich dabei helfen werden, zukünftige Projekte besser zu strukturieren. Lassen Sie uns zunächst einige der gängigen Ordnerstrukturen und ihre Probleme besprechen.
Meiner Erfahrung nach gibt es vier Arten von Ordnerstrukturen: zufällig, nach Asset-Typ, nach Funktion und nach Zweck. Von diesen ist die letzte bei weitem die beste, da sie die Absicht vermittelt und sich daher am besten für eine optimale Bündelungsstrategie eignet.
„Zufall“ sehe ich nicht oft. Dies geschieht vor allem bei Einzelentwicklern, die mit der Softwareentwicklung möglicherweise nicht vertraut sind, und wird aus offensichtlichen Gründen unhaltbar, wenn ein Projekt an Größe oder Komplexität zunimmt. Das Fehlen einer Struktur oder eine zufällige Struktur bringt viele Probleme mit sich – Vermögenswerte sind schwer zu finden und der beabsichtigte Verwendungszweck ist praktisch unmöglich zu verstehen.
Die Strukturierung nach Asset-Typ ist weit verbreitet, da viele Künstler auf diese Weise an Assets arbeiten, bevor sie diese in die Engine importieren. Wenn Sie den Asset-Typ kennen, ist es einfach, seinen Standort zu finden, alles andere darüber ist jedoch unklar. Selbst bei einer guten Namenskonvention kann es schwierig sein zu erkennen, ob ein Charakter, eine Umgebung, eine Benutzeroberfläche oder eine beliebige Kombination dieser drei einen bestimmten Shader, eine bestimmte Textur, ein bestimmtes Mesh usw. erfordert. Ein geeignetes Dateiverzeichnis sollte Informationen nicht verschleiern, sondern offenlegen.
Ordnerstrukturen nach Features sind zwar selten, erscheinen aber auf den ersten Blick sinnvoll. Viele Unternehmen unterteilen sich in Feature-Teams. Warum also die Daten nicht ähnlich gruppieren? Allerdings verwendet das Spiel die Daten nicht auf diese Weise. In der Vergangenheit habe ich Beispiele wie Shader und Audio gesehen, die zusammen gebündelt werden sollten, aber da sie von verschiedenen Teams erstellt werden, wird dieser Sachverhalt verschleiert.
Ein Dateiverzeichnis mit einer klaren, auf dem Zweck der Assets basierenden Namenskonvention umgeht diese Probleme. Um dies zu veranschaulichen, verwende ich ein fiktives Spielbeispiel namens „Dinosaur Brawl“.
Für dieses Beispiel ist Dinosaur Brawl ein 3D -Action-Adventure-Spiel in der Third-Person-Perspektive, bei dem der Spieler einen Dinosaurier auswählt, den er in einer riesigen offenen Welt mit mehreren Biomen steuert. Dabei kämpft er gegen andere Dinosaurier und prähistorische Kreaturen, um stärker zu werden und seine Gene an die nächste Generation weiterzugeben – und das alles in einem gigantischen Kampf ums Überleben in der kommenden Eiszeit. Das Spiel ist für Mobilgeräte konzipiert und einige der Daten werden als Teil der Originalanwendung verteilt. Der Rest wird nach Bedarf von einem CDN heruntergeladen.
Aus der obigen Übersicht können wir eine allgemeine Ordnerstruktur für das gesamte Projekt erstellen. Da der Spieler andere Dinosaurier auswählen und gegen sie kämpfen kann, ist es sinnvoll, pro Dinosaurier einen Ordner zu erstellen, der alle für diesen Dinosaurier spezifischen Assets enthält: Meshes, Soundeffekte, Texturen, Animationen, Partikeleffekte usw. Ich werde diese als einzigartige Vermögenswerte kategorisieren.
Da es sich um ein Actionspiel handelt, wird es Umgebungen geben, die separate Biome sind. Wir sollten daher für jedes Biom oder Level im Projekt einen einzelnen Ordner erstellen: Ebenen, Wüsten, Tundra, Sümpfe, Vulkane usw.
Natürlich wird es auch Assets geben, deren Vorhandensein für ganze Abschnitte des Spiels erforderlich ist. Ein solcher Satz sind UI-Elemente. Sie können sich diese Vermögenswerte als globale Vermögenswerte vorstellen. So wie wir einen Ordner für alle einzigartigen Assets erstellt haben, sollte es einen globalen Ordner geben, der ganz oben in der Ordnerhierarchie steht. Beispielsweise ein globaler UI-Ordner, ein globaler Dinosaur-Ordner, ein globaler Environment-Ordner und so weiter. Auf diese Weise werden alle von diesen Spielabschnitten gemeinsam genutzten Dinge an einem Ort gespeichert.
Diese Vermögenswertkategorie wird so definiert, dass sie von einigen, aber nicht allen einzigartigen Vermögenswerten gemeinsam genutzt wird. Daher passen sie weder in die Kategorie „Globale Vermögenswerte“ noch in die Kategorie „Einzigartige Vermögenswerte“. Ein Beispiel für diese Art gemeinsam genutzter Assets bei Dinosaur Brawlkönnten solche sein, die bei allen Flugdinosauriern vorhanden sind, wie etwa Partikel, Shader und Soundeffekte, die erforderlich sind, um das Gefühl zu vermitteln, durch die Luft zu schweben.
Was häufig passiert, ist, dass diese Assets in den Ordner für den ersten Dinosaurier gelegt werden, der sie braucht. Leider wird hier nicht genau beschrieben, wie sie verwendet werden sollen, wodurch ihr Zweck unklar bleibt. Im schlimmsten Fall werden Assets in jedem Flying Dinosaur-Paket dupliziert, was sich negativ auf Speicher, Debugging und Anwendungsgröße auswirkt.
Die beste Lösung besteht darin, einen neuen Ordner mit einem Namen zu erstellen, der den Verwendungszweck angibt, beispielsweise „Fliegende Dinosaurier“. Die genaue Festlegung des Standorts ist schwieriger; es gibt keinen Standard. Ich bevorzuge es, diese in einem Unterordner auf derselben Ebene wie die globalen und eindeutigen Dinosaurierordner abzulegen, aber es ist genauso gut möglich, sie zusammen mit anderen eindeutigen Ordnern abzulegen.
Ein typischer Sonderfall dieser Konvention liegt vor, wenn sich die Projektanforderungen ändern und ein ursprünglich als einzigartig vorgesehener Vermögenswert gemeinsam genutzt wird. Um in unserem Dinosaur Brawl -Beispiel Entwicklungszeit zu sparen, wird entschieden, das Velociraptor-Prefab als Basis für alle anderen Raptoren (wie etwa Utahraaptor, Dokataraptor usw.) zu verwenden.
Was die Entwickler jedoch nicht wissen: Wenn das Velociraptor-Prefab zu einem Paket hinzugefügt wird, werden alle Velociraptor-Assets heruntergeladen, wenn alle anderen Raptoren geladen werden. Dadurch verlängern sich die Downloadzeiten, obwohl nur das Prefab verwendet wird.
Dies geschah, weil die Absicht des Assets geändert wurde und die Ordnerstruktur dies nicht mehr widerspiegelt. Wenn sich die Absicht ändert, sollten der Standort und der Name des/der Assets entsprechend aktualisiert werden, um die Konsistenz und Genauigkeit im System zu gewährleisten. Dadurch wird dem Team, das die Pakete erstellt, mitgeteilt, welche Assets in einem „Shared Raptor“-Paket enthalten sein sollten und welche im einzigartigen Velociraptor-Modell verbleiben sollten.
Einer der häufigsten und am schwierigsten zu behebenden Sonderfälle liegt vor, wenn ein Vermögenswert unbeabsichtigt auf eine Weise verwendet wird, für die er nie vorgesehen war. Wenn dies geschieht, handelt es sich normalerweise um einen Unfall. Beispielsweise muss jemand eine Frist einhalten und verwendet ein bereits vorhandenes Asset im Projekt, um die Arbeit schnell abzuschließen.
Nehmen wir dieses Szenario: Ein Künstler fügt ein Tutorial für eine bevorstehende Erweiterung von Dinosaur Brawl hinzu und findet einen „Gold Glow“-Shader, um hervorzuheben, wann Spieler einen Gegenangriff auf Elitefeinde starten können. Was der Künstler nicht weiß ist, dass es sich bei diesem Shader um Endspielinhalt gegen einen riesigen T-Rex handelt – es handelt sich um einen einzigartigen Boss, der viele gebündelte Assets enthält. Jetzt werden alle diese Assets während des Tutorials an einen Ort heruntergeladen, an dem die meisten Assets nicht verwendet werden. Dieses Paket ist riesig, sodass das System, das normalerweise kleinere Assets wie dieses mitten im Spiel herunterlädt, stark beansprucht wird. Dies kann alles von Leistungsspitzen bis hin zu Abstürzen verursachen, weil das Asset von Spielern mit schlechter Verbindung nicht schnell genug heruntergeladen werden kann.
Das oben genannte ist ein extremes, aber durchaus realistisches Beispiel, das ich in mehr als einem Projekt erlebt habe. Aus diesem Grund sollten alle Assets zusätzlich zur Ordnerstruktur einen Namen haben, der ihren Zweck vermittelt. Würde der Shader beispielsweise „gold_glow_trex_endgame“ heißen, wäre der Verwendungszweck klar ersichtlich. Beim Debuggen wäre es dann offensichtlich, dass dieses Asset während des Tutorials nicht geladen werden sollte.
Wenn Sie mit Addressables vertraut sind, wissen Sie vielleicht, dass Gruppen und Labels zum Gruppieren und Labeln von Assets verwendet werden, und zwar auf die gleiche Weise, wie ich es im obigen Spielbeispiel vorgeschlagen habe – durch die Verwendung von Ordnern und sinnvollen Namenskonventionen. Sie fragen sich vielleicht: „Warum sich mit all dem herumschlagen, wenn Sie dies auch mit Gruppen und Beschriftungen erledigen können?“
Meine Antwort ist, dass Sie beides tun sollten. Wie ich eingangs erklärt habe, wird es mit der wachsenden Zahl von Assets in einem Projekt für eine einzelne Person schwieriger und schließlich unmöglich, zu wissen, wie alle Assets verwendet werden sollen. Wenn Sie wissen, dass die Addressables Gruppen mit der Ordnerstruktur übereinstimmen sollten, können Sie bestätigen, dass sie korrekt eingerichtet sind.
Ich habe gesehen, dass viele unserer Kunden Asset Bundles ohne Addressables verwenden und als Lösung für dieses Problem komplexe Systeme codieren. Sie erstellen und verwalten beispielsweise eine Masterliste, die zum Erstellen der Pakete verwendet wird, oder überprüfen Versionskontroll-Commits, um Änderungen in Paketen usw. zu vergleichen. Meiner Erfahrung nach sind diese Lösungen auf lange Sicht nicht kosteneffizient. Es handelt sich um ein weiteres System, das entwickelt und gewartet werden muss, was zusätzliche Fehlerquellen schafft. Mit zunehmender Skalierung des Projekts geraten sie unter einer Vielzahl von Ausnahmen und Grenzfällen in Schwierigkeiten, die bei langlebigen Projekten naturgemäß auftreten. Und das Schlimmste ist, dass sie auf grundsätzlicher Ebene versagen, weil sie keine Lösung für Benutzerfehler bieten.
Ein gut strukturiertes Ordnersystem und eine gute Dateibenennungskonvention sollten zu einer 1:1-Übereinstimmung für Asset-Bundles und adressierbare Gruppen führen. Durch die Kategorisierung von Dateien in logische Gruppen und Unterordner wird sichergestellt, dass alle Teammitglieder die Dateien einheitlich interpretieren und finden. Dadurch werden potenzielle Missverständnisse und Unstimmigkeiten bei Personalwechseln und sich ändernden Projektanforderungen vermieden. Asset-Ersteller können einen einfachen Zugriff und eine einfache Navigation ermöglichen und so anderen Teammitgliedern die zeitaufwändige Suche nach bestimmten Assets ersparen. Ein systematischer Ansatz spart wertvolle Zeit und minimiert die Wahrscheinlichkeit von Fehlern und Versehen. Werden Sie zu einem dauerhaften Bezugspunkt, einer Quelle der Wahrheit, erleichtern Sie den Onboarding-Prozess für neue Teammitglieder und stellen Sie die Realisierbarkeit des Projekts im Laufe der Zeit sicher.
Benötigen Sie Unterstützung oder Rat zur Ordnerstruktur? Chatten Sie mit uns in den Foren. Und sehen Sie sich weitere technische Blogs von Unity Entwicklern an, als Teil der laufenden Technik aus der Trenches-Reihe.
