Sollten Verweise zwischen Assets nach Name oder ID oder etwas anderem behandelt werden?

7

Wie sollten Inhalte oder Asset-Elemente in ihrer serialisierten Form referenziert werden?

Beispielsweise muss ein Material möglicherweise auf mehrere Texturen verweisen. Am einfachsten wäre es, einen Pfad relativ zum Basisverzeichnis der Assets zu verwenden.

Alternativ können alle Inhaltselemente durch eine ID referenziert werden. Ich habe es auf diese Weise implementiert (mithilfe von GUIDs), wodurch Inhaltselemente umbenannt oder verschoben werden können, ohne dass Referenzen verletzt werden. Dies macht es jedoch schwieriger, ein Inhaltselement zu ersetzen (das Original löschen und dann etwas anderes in denselben Namen umbenennen ... erfordert das Kopieren / Einfügen von GUIDs). Außerdem wird das Debuggen fehlender Inhalte schwieriger.

Gibt es hier eine klare Gewinnoption?

Robert Fraser
quelle
Ich habe UUIDs verwendet, und sie scheinen einfach zu generieren zu sein und haben eine lächerlich geringe Kollisionswahrscheinlichkeit
Alex Stone

Antworten:

8

String-Keying / Hashmaps

  • Sind schnell, da die Lesezeit O (1) amortisiert wird, was bedeutet, dass der Lesezugriff normalerweise sehr schnell ist, aber im schlimmsten Fall (selten, aber nicht unbekannt) kann er ziemlich langsam sein. Der schlimmste Fall resultiert aus Hash-Kollisionen.

  • Implementierungen müssen manchmal erstellt oder gefunden werden (z. B. in C). Das Schreiben / Finden einer performanten Map-Implementierung mit Zeichenfolgenschlüssel kann nicht trivial sein.

  • Zeichenfolgenvergleiche können teuer sein. Ob dies relevant ist, hängt jedoch von der Implementierung von Hashmap-Leseoperationen in Ihrer Sprache und der Implementierung der Zeichenfolgengleichheit ab.

  • Möglicherweise können Sie versehentlich Duplikate erstellen oder vorhandene Werte überschreiben (abhängig von der Implementierung).

Numerisches Keying / Arrays

  • Sind sehr schnell, da die Struktur, die Sie hinzufügen, direkt dem Speicher zugeordnet wird (gemäß Arrays in den meisten Sprachen)

  • Sind sehr schnell, da die numerische Gleichheit schnell überprüft wird (zumindest für ausreichend kleine Bitbreiten)

  • Sind sehr schnell, da lange, zusammenhängend zugewiesene Arrays eine hervorragende Cache-Leistung aufweisen können (Einschränkung: Dies hängt sehr stark von Ihrer Wahl der Sprache und Implementierung ab).

  • Erfordern, dass Ihre "GUID" nicht zu groß ist, um als Array-Index zu fungieren. Es gibt jedoch schnelle Optionen, um dies zu umgehen, z. B. das Aufbrechen Ihrer ID (über Bit-Ops), um sie als zwei ausreichend kurze Indizes pro Element in einem 2D-Array zu verwenden.

  • Sind aus den von Ihnen genannten Gründen unpraktisch. Wenn es sich bei den IDs um Kompilierungszeitwerte handelt, mit denen Sie entwickeln müssen, ist dies weniger problematisch, da sie ALL CAPS-Konstanten mit entsprechendem Namen zugewiesen und auf diese Weise verwendet werden können.

  • Kann auf Strukturen verweisen, die einen lesbaren Namen enthalten. Dies bietet einige Annehmlichkeiten, auch wenn unter diesem Namen nicht auf sie zugegriffen werden kann.

Fazit

Wenn Sie nicht viele Elemente (z. B. Zehntausende) pro 16 bis 20 ms Tick mit einer dieser Optionen verarbeiten, würde ich mir keine Gedanken über numerische IDs machen, insbesondere wenn Sie eine Sprache verwenden, in der bereits effiziente Hashmaps verfügbar sind , entscheiden Sie sich einfach für eine Hashmap.

Andernfalls ist der numerische ID / Array-Ansatz gut geeignet, um CPU-Zyklen zu sparen. Dies ist jedoch in Fällen der Fall, in denen Ressourcen knapp werden.

Ingenieur
quelle
6

Ich würde die Verwendung von IDs und insbesondere von GUIDs nachdrücklich befürworten. GUIDs haben eine Reihe hervorragender Vorteile:

  • Sie können lokal generiert werden und behalten dennoch ihre Einzigartigkeit. Einfache numerische IDs erfordern eine zentrale Behörde, um die Eindeutigkeit zu gewährleisten. Dies macht die Verwendung sofort umständlicher, wenn mehr als eine Person an einem Projekt arbeitet.

  • Das Ändern des Namens eines Assets erfordert nicht den teuren Vorgang, alle Verweise auf diesen alten Namen zu suchen und zu aktualisieren. Dies ist nicht nur fehleranfällig, es auch hat schwere Probleme in einer Welt , wo viele Menschen auf einem Datensatz zusammenarbeiten , (wenn jemand an einer Datei arbeiten Referenzierung das Sie ändern möchten , dann entweder sind Sie gezwungen , zu warten , oder sie sind gezwungen, die Zusammenführung aufzulösen).

  • Vermögenswerte um im Dateisystem oder logische Hierarchie des Content Store Umzug erfordert keine Referenzen Aktualisierung entweder .

GUIDs haben zwar Nachteile, sind aber alle mit geringem Aufwand lösbar.

  • Sie sind schwer zu merken und zu tippen, was bedeutet, dass es schwierig sein kann, mit einem anderen Benutzer zusammenzuarbeiten ("Objekt anzeigen {CD0B6FBB-1156-4BCF-A5EB-82967376090E}" ist etwas umständlich). Sie können jedoch in Ihre Toolchain zur Asset-Bearbeitung eine Möglichkeit einbauen, Objekte nach Namen zu suchen, oder noch besser ein URL-Schema für Ihre Tools erstellen, mit dem Sie anklickbare Links generieren können, mit denen die Tools geladen werden, die das gewünschte Asset anzeigen.

  • Sie sind groß. Dies ist im Allgemeinen während der Entwicklung nicht so wichtig, sondern dient dem Versand des Codes. Es ist jedoch sehr einfach, einen Schritt zur Datenkompilierungszeit zu unterstützen, der beim Backen des endgültigen Inhalts für das Spiel eine Neuzuordnung von GUIDs zu ganzzahligen IDs erzeugt.

In Guild Wars 2 haben wir zu Beginn der Entwicklung mehrere Jahre lang benannte Verweise auf Inhalte verwendet. Es war die falsche Entscheidung und hat die Leistung unserer Tools für einige Zeit beeinträchtigt, bevor wir auf GUIDs umsteigen konnten. Jedes Projekt, an dem ich jemals gearbeitet habe und das benannte Referenzen verwendet hat, hatte Probleme mit ihnen, daher würde ich es absolut empfehlen. Der Aufwand für die Erstellung der Toolunterstützung für GUIDs ist auf lange Sicht geringer als für die Bewältigung benannter Referenzen.

Wenn Sie ein kleines Projekt haben, nur durch sich selbst oder vielleicht eine Handvoll andere können Sie mit der Verwendung von IDs weg (was jeder Person einen eigenen „Block“ von IDs, zum Beispiel, kann leicht das Aufeinanderprallen Problem für einige Zeit vermeiden). Aber wenn Sie der Aufwand für GUIDs ein kleines Projekt haben , ist nicht wahrscheinlich problematisch sein , entweder , so würde ich nur sagen , dass Sie die für die beste künftige Skalierbarkeit nutzen sollten.


quelle
1

Es ist einfacher, darüber nachzudenken, wenn Sie zwischen externen und internen Bezeichnern unterscheiden. Ein Asset verfügt über eine eindeutige externe Kennung, auf die in Konfigurationsdateien, Makefiles, Dokumentationen usw. verwiesen wird. Sobald ein Asset in Ihre Anwendung geladen wurde, erhalten die Assets möglicherweise eine effiziente interne Kennung für die interne Referenzierung.

Für die externe Kennung würde ich ein konsistentes Namensschema verwenden, das der Konvention über das Konfigurationsparadigma folgt . Daher möchten Sie möglicherweise ein pfadbasiertes Schema wie "Ressourcen / Texturen / Wände / Beton.png" verwenden. Diese Kennungen sagen viel aus: dass es sich um eine Ressource handelt, dass es sich um eine Textur handelt, dass sie zu den 'Wänden' der Texturgruppe gehört und sogar dort, wo sie sich auf der Festplatte befindet. Außerdem ist es für Menschen lesbar, viel mehr als eine GUID.

Für die interne Kennung können Sie entweder Speicherorte (Zeiger), zunehmende Ganzzahlen oder GUIDs verwenden. Natürlich können Sie auch die externe Kennung als Identitätskennung verwenden, was zu einer höheren Speichernutzung und einer langsameren Leistung führt.

Um eine interne Kennung von Ihrer externen Kennung zu erhalten, benötigen Sie höchstwahrscheinlich ein zentrales Mapping / Repository in Ihrer Anwendung. In der Regel kann hierfür der Ressourcenmanager verwendet werden, der Ihre Ressourcen lädt.

Zum Schluss noch der Punkt, an dem Referenzen fehlen: Da Ressourcen normalerweise zur Laufzeit verzögert geladen werden, sollten Sie ohnehin eine Art Testsuite oder Integritätsprüfung für Ihre Anwendung durchführen lassen, sodass ich nicht denke, dass es wichtig ist, welche Art von Kennung Sie verwenden Schema, das Sie verwenden werden.

Bas Geertsema
quelle
0

Es gibt keinen besten Ansatz, da er immer vom tatsächlichen Anwendungsfall und Ihrer Gesamtarchitektur abhängt.

Die Verwendung von IDs oder GUIDs ist nicht unbedingt einfacher zu verwenden oder zu ersetzen. Denken Sie daran, dass Sie diese auch kopieren und verwenden müssen. Insbesondere GUIDs sind in der Regel ziemlich lang und ohne Copypasting schwer zu merken. Gleiches kann für rohe Zahlen gelten.

Daher sind "sprechende" Namen wahrscheinlich der beste Ansatz, selbst wenn dies mehr Schreiben oder Ersetzen erfordert.

Was Sie tun können, ist die Verwendung einer Kennung mit fester Länge. Sie können beispielsweise 4 alphanumerische Zeichen verwenden, um alles zu identifizieren. Dies hat auch den zusätzlichen Vorteil, dass Sie die ID (Zeichenfolge) einfach in eine Ganzzahl umwandeln können (berücksichtigen Sie nur die Unterschiede in der Bytereihenfolge) und diese schnell vergleichen können.

Dies kann auch auf den Dateinamen erweitert werden, sodass Sie auch nicht auf vollständige Pfade verweisen müssen. Wenn ich beispielsweise "NMY1" für meinen ersten Feind verwende, werden die Daten in der Datei "NMY1.dat" gespeichert, wobei die Textur in "NMY1.png", der Skriptcode in "NMY1.lua" usw. gespeichert ist.

Eine andere Sache wäre die Modifizierbarkeit: Wenn Sie möchten, dass Benutzer Ihr Spiel einfach modifizieren können, versuchen Sie, eine Überoptimierung zu vermeiden. Dh lieber Namen als Abkürzungen sprechen, keine Roh-IDs oder GUIDs verwenden und stattdessen etwas verwenden, das leichter zu lesen / verstehen / kopieren ist, auch wenn dies bedeutet, dass Sie möglicherweise auch viele Referenzen aktualisieren müssen.

Wenn Ihre Daten zu komplex werden, um einfach aktualisiert / überprüft zu werden, schreiben Sie Tools, die dies für Sie tun (und auch die Integrität überprüfen), oder überdenken Sie Ihren Ansatz.

Mario
quelle