Identifizieren von Assets in einer Game Engine?

12

Ich möchte mein geladenes Guthaben identifizieren, weiß aber nicht, welches ich auswählen soll. Es gibt 2 Möglichkeiten:

  • Name (Zeichenfolge)

    • Dies ist am einfachsten und auch am schnellsten mit unordered_map (O (1)), aber viel langsamer als mit ganzen Zahlen.
    • Leicht verständlich im Code.
  • Ganze Zahlen

    • Am schnellsten
    • Sind im Code nicht verständlich.

Ich weiß, dass Saiten nicht so sicher oder schnell sind, aber ist sie so schlecht oder zählt sie in einem AAA-Titel nur als schlecht? Ich könnte Aufzählungen erstellen, um Ganzzahlen zu verwenden, aber wenn ich die Szene, Assets usw. zur Laufzeit aus einer Datei lade, kann ich keine Aufzählungen verwenden. Gibt es eine Möglichkeit, diese Ganzzahlen lesbar zu machen, wenn sie zur Laufzeit generiert werden?

Ich weiß, dass dieses Problem einige Themen rund um das Internet hat, aber ich konnte nicht herausfinden, in welchen Fällen dies wichtig ist.

Tudvari
quelle
10
Warum nicht eine Implementierung von beidem? Die String-Version stellt eine Verbindung zu einem Dictionary <string, int> her, das seinerseits ein Dictionary <int, Asset> aufruft. Sie können die auf Zeichenfolgen basierende Ebene im Code umgehen, die auf Zeichenfolgen basierende Ebene jedoch für die Benutzerinteraktion verwenden.
Krythic
2
Ich würde @ Krythic Punkt zweitens. Wenn Ihr Code Ganzzahlen für die Geschwindigkeit mag, lassen Sie Ihren Code Ganzzahlen verwenden. Wenn Ihre Benutzer Zeichenfolgen für die Lesbarkeit mögen, lassen Sie Ihre Benutzer Zeichenfolgen verwenden. Die beiden können recht glücklich nebeneinander existieren (und Sie können die String-Version nur dann selektiv in Entwicklungs-Builds kompilieren, wenn Sie den Overhead in Release vollständig überspringen möchten)
DMGregory
Gleiches Problem in einem etwas anderen Kontext: Unterschiedliche Methoden der Artikelimplementierung - was sind die Unterschiede?
Philipp

Antworten:

19

Sie können beide unterstützen.

Während es zur Laufzeit oft effizienter ist, Assets mit einer Ganzzahl oder einem ähnlichen, schnell zu vergleichenden Schlüssel zu referenzieren, ist es zur Entwurfszeit oft effizienter, sie mit Namen zu referenzieren, da Menschen mit Namen wie viel besser umgehen können enemy_bullet_casing_soundals 72910613.

Verwenden Sie einen Ganzzahlschlüssel, um die Ressourcen direkt nachzuschlagen, und verwenden Sie diese Ganzzahl nach Möglichkeit im Code (wobei Sie den tatsächlichen Wert der Ganzzahl in eine Variable einfügen und damit einfacher arbeiten können). Geben Sie eine Zuordnung von name zu diesem Ganzzahlschlüssel (und nicht direkt zur Ressource) an und verwenden Sie diese Zuordnung, wenn Sie auf benannte Verweise auf Assets stoßen, um den tatsächlichen Ganzzahlschlüssel aufzulösen und das Asset zu finden.

Durch die Verwendung der namensbasierten Suche wird die Arbeit mit Ihren Datendateien erheblich vereinfacht, und durch die Zuordnung des Namens zu einem schnelleren Schlüssel bleiben alle wichtigen Vorteile eines schnelleren Schlüssels vom Typ Integer erhalten, wo immer er benötigt wird.


quelle
Mein Fall: Ich möchte das Material eines Objekts ändern und sende eine Anfrage mit dem Namen des neuen Materials. (string) Dann wird im Grafiksystem in einer ungeordneten Map <string, pointer> gesucht, und der Zeiger des Objektmaterials wird durch den neuen Zeiger ersetzt. Also muss ich es in meinem Fall nicht in eine Ganzzahl konvertieren? (Da ich es in Zeiger konvertiere und in den häufigen Algorithmen Zeiger verwende, verwende ich nur gelegentlich Zeichenfolgen.)
Tudvari
Oder sollte ich Integer-IDs anstelle von Zeigern überall dort verwenden, wo es möglich ist? (Ich muss also nicht die Header-Datei des Materials einschließen.) Beispielsweise speichert die Renderer-Komponente jetzt den Zeiger des verwendeten Materials, der direkt von der Grafik-Engine verwendet werden kann, aber ich muss Material.h einschließen . Wenn ich jedoch nur Ganzzahlen in der Rendererkomponente speichere, muss ich Material.h nicht einschließen, sondern eine ganzzahlige Suche im Array der Zeiger durchführen. Ich denke, das letztere ist besser. Ist es? Soll ich das umgestalten?
Tudvari
1

In meinem Projekt verwende ich Hash-Strings, die zur Kompilierungszeit in eindeutige (ich wünsche!) Zahlen umgewandelt werden. Wenn ich also eine Ressource benötige, zum Beispiel eine Textur, rufe ich einfach auf

MngTexture->get(hash("my_texture"))

Und da ich ein einfaches Entity-System-Framework erstelle und Komponentendaten aus Dateien laden muss, habe ich eine einfache Sprache wie json erstellt, um Daten zu speichern, die aber kompilierbar ist (Umwandlung von Wörtern und Zeichen von Ziffern in Zahlen und von Zeichenfolgen in Hash-Werte). . Wenn ich zum Beispiel die Textur mit dem ID-Hash ("my_texture") mit "ball.PNG" in meiner Datendatei verknüpfen möchte, habe ich

|my_texture| = "ball.PNG"

Wo || ist ein Operator, der dem Compiler sagt, dass er das Wort darin hashen soll.

Im Grunde genommen verwende ich also Zeichenfolgen, die beim Kompilieren auf ints abgebildet werden (damit sie keinen Overhead verursachen), sowohl im eigentlichen Code als auch in den Dateien, die die Streams zum Laden von Komponenten darstellen. Für die Berechnung des Hashs eine Kompilierzeit einfach googeln, es ist eine einfache Funktion von 5-10 Codezeilen.

Natürlich können Sie den String aus Ihren Dateien laden und zur Laufzeit haschen. In diesem Fall müssen Sie das Wörterbuch nicht selbst schreiben, da der Algorithmus dies für Sie (Erstellen von Ganzzahlen aus Strings) und mich erledigt Ich denke, dass Hasing aufgrund der Speicherlokalität mindestens so schnell ist wie das Suchen in einer Karte (Sie durchlaufen lediglich eine Zeichenfolge, die nur wenige Bytes lang ist).

Hoffe das kann helfen.

Liuka
quelle
0

Das Erkennen von Objekten anhand von Zeichenfolgen ist nicht optimal, da Ints viel effizienter sind. Der Einfachheit halber können Sie eine Zeichenfolgentabelle (oder ein Wörterbuch) mit Zeichenfolgen in Ints verwalten, um Sie bei der Entwicklung und beim Debuggen zu unterstützen.

Ich würde jedoch befürworten, dass Sie in Ihrem Hauptspielcode Objekte nur anhand ihrer Ganzzahl-ID (oder einer Aufzählung zur besseren Lesbarkeit) referenzieren. Auf diese Weise können Sie die Zeichenfolgentabelle einfacher als separates Asset aufteilen. Wenn sich Ihr Hauptspielcode nicht auf diese Zeichenfolgentabelle stützt, können Sie ihn aus dem veröffentlichten Spiel entfernen, wodurch möglicherweise eine erhebliche Menge an Speicher eingespart wird. Dies ist ein wichtiger Gesichtspunkt, wenn Sie an einem Mobilspiel arbeiten und die Downloadgröße so gering wie möglich halten möchten möglich.

steeveeet
quelle