Kerntypen

Godot hat eine Vielzahl von Klassen und Vorlagen, aus denen sich sein Kern zusammensetzt, und alles baut darauf auf.

Diese Referenz wird versuchen sie aufzulisten, um sie besser zu verstehen.

Definitionen

Godot verwendet die Standard-C99-Datentypen wie uint8_t, uint32_t, int64_t usw., die heutzutage von jedem Compiler unterstützt werden. Das Rad für diese neu zu erfinden macht keinen Spaß, da es das Lesen von Code erschwert.

Im Allgemeinen wird nicht darauf geachtet, den effizientesten Datentyp für eine bestimmte Aufgabe zu verwenden, es sei denn, Sie verwenden große Strukturen oder Arrays. int wird im größten Teil des Codes verwendet, sofern dies nicht erforderlich ist. Dies geschieht, weil heutzutage jedes Gerät mindestens einen 32-Bit-Bus hat und solche Operationen in einem Zyklus ausführen kann. Es macht Code auch lesbarer.

Für Dateien oder Speichergrößen wird size_t verwendet, die garantiert 64 Bit beträgt.

Für Unicode-Zeichen wird CharType anstelle von wchar_t verwendet, da viele Architekturen ein 4 Bytes langes wchar_t haben, wobei 2 Bytes möglicherweise erwünscht sind. Standardmäßig wurde dies jedoch nicht erzwungen und CharType wird direkt wchar_t zugeordnet.

Referenzen:

Speichermodell

PC ist eine wunderbare Architektur. Computer verfügen häufig über Gigabytes an RAM, Terabytes an Speicher und Gigahertz CPU. Wenn eine Anwendung mehr Ressourcen benötigt, lagert das Betriebssystem die inaktiven aus. Andere Architekturen (wie Mobilgeräte oder Konsolen) sind im Allgemeinen eingeschränkter.

Das gebräuchlichste Speichermodell ist der Heap, bei dem eine Anwendung einen Speicherbereich anfordert und das zugrunde liegende Betriebssystem versucht, ihn irgendwo anzupassen und zurückzugeben. Dies funktioniert oft am besten und ist flexibel, aber im Laufe der Zeit und bei Missbrauch kann dies zu einer Segmentierung führen.

Durch die Segmentierung werden langsam Löcher erzeugt, die für die meisten gängigen Zuordnungen zu klein sind, sodass Speicherplatz verschwendet wird. Es gibt viel Literatur über Heap und Segmentierung, daher wird auf dieses Thema hier nicht weiter eingegangen. Moderne Betriebssysteme verwenden ausgelagerten Speicher, wodurch das Segmentierungsproblem zwar gemindert, aber nicht gelöst wird.

In vielen Studien und Tests wurde jedoch gezeigt, dass bei ausreichendem Speicher die Segmentierung im Laufe der Zeit kein Problem darstellt, wenn die maximale Zuordnungsgröße im Verhältnis zur maximalen Heap-Größe und zum Anteil des Speichers, der nicht verwendet werden soll, unter einem bestimmten Schwellenwert liegt wie es konstant bleiben wird. Mit anderen Worten, lassen Sie 10-20% Ihres Speichers frei und führen Sie alle kleinen Zuweisungen durch, und alles ist gut.

Godot stellt sicher, dass alle Objekte, die dynamisch zugewiesen werden können, klein sind (höchstens einige KB). Aber was passiert, wenn eine Zuordnung zu groß ist (z.B. ein Bild oder eine Mesh-Geometrie oder ein großes Array)? In diesem Fall hat Godot die Möglichkeit einen dynamischen Speicherpool zu verwenden. Dieser Speicher muss gesperrt sein, damit auf ihn zugegriffen werden kann. Wenn einer Zuordnung der Speicherplatz ausgeht, wird der Pool bei Bedarf neu angeordnet und komprimiert. Abhängig von den Anforderungen des Spiels kann der Programmierer die Größe des dynamischen Speicherpools konfigurieren.

Speicher zuweisen

Godot verfügt über viele Tools zum Verfolgen der Speichernutzung in einem Spiel, insbesondere während des Debuggens. Aus diesem Grund sollten die regulären C und C++ Bibliotheksaufrufe nicht verwendet werden. Stattdessen werden einige andere bereitgestellt.

Für die Zuweisung im C-Stil bietet Godot einige Makros:

memalloc()
memrealloc()
memfree()

Diese entsprechen dem üblichen malloc, realloc, freigeben aus der Standard C-Bibliothek.

Für die Zuweisung im C++ Stil stehen spezielle Makros zur Verfügung:

memnew( Class / Class(args) )
memdelete( instance )

memnew_arr( Class , amount )
memdelete_arr( pointer to array )

die äquivalent zu new, delete, new [] und delete [] sind.

memnew/memdelete verwenden auch eine kleine C++-Magie und benachrichtigen Objekte direkt nach ihrer Erstellung und direkt vor dem Löschen.

Für den dynamischen Speicher wird das PoolVector<> Template bereitgestellt. PoolVector ist eine Standardvektorklasse und dem Vektor in der C++ - Standardbibliothek sehr ähnlich. Verwenden Sie Folgendes, um einen PoolVector-Puffer zu erstellen:

PoolVector<int> data;

Auf PoolVector kann mit dem Operator [] zugegriffen werden. Hierzu gibt es einige Helfer:

PoolVector<int>::Read r = data.read()
int someint = r[4]
PoolVector<int>::Write w = data.write()
w[4] = 22;

Diese Operationen ermöglichen ein schnelles Lesen/Schreiben von PoolVectors und halten es gesperrt, bis sie den Gültigkeitsbereich verlassen. PoolVectors sollten jedoch für kleine, dynamische Speicheroperationen verwendet werden, da read() und write() für eine große Anzahl von Zugriffen zu langsam sind.

Container

Godot bietet auch eine Reihe gängiger Container:

  • Vektor

  • List

  • Set

  • Map

Sie sind einfach und sollen so minimal wie möglich zu sein, da Vorlagen in C++ häufig inline sind und die Binärgröße sowohl in Debug-Symbolen als auch den Code aufblähen. List, Set und Map können mit folgenden Zeigern iteriert werden:

for(List<int>::Element *E=somelist.front();E;E=E->next()) {
    print_line(E->get()); // print the element
}

Die Vector<> -Klasse hat auch ein paar nette Funktionen:

  • Sie kopiert beim Schreiben, daher ist das Erstellen von Kopien günstig, solange sie nicht geändert werden.

  • Sie unterstützt Multithreading durch Verwendung kleinster Operationen am Referenzzähler.

Zeichenkette

Godot bietet auch eine String-Klasse. Diese Klasse bietet eine Vielzahl von Funktionen, vollständige Unicode-Unterstützung für alle Funktionen (z.B. Falloperationen) und das Parsen bzw. Extrahieren von utf8 sowie Helfer für die Konvertierung und Visualisierung.

Referenzen:

StringName

StringNames sind wie ein String, sind aber eindeutig. Das Erstellen eines StringName aus einem String führt zu einem eindeutigen internen Zeiger für alle gleichen Strings. StringNames sind nützlich um Strings als Bezeichner zu verwenden, da beim Vergleich im Grunde genommen ein Zeiger verglichen wird.

Die Erstellung eines StringName (insbesondere eines neuen) ist langsam, der Vergleich jedoch schnell.

Referenzen:

Mathe-Typen

Im Verzeichnis core/math stehen mehrere lineare Mathe-Typen zur Verfügung.

Referenzen:

NodePath

Dies ist ein spezieller Datentyp, mit dem Pfade in einem Szenenbaum gespeichert und schnell referenziert werden.

Referenzen:

RID

RIDs sind Ressourcen-IDs. Server verwenden diese um auf darin gespeicherte Daten zu verweisen. RIDs sind undurchsichtig, was bedeutet, dass auf verwiesene Daten nicht direkt zugegriffen werden kann. RIDs sind eindeutig, auch für verschiedene Arten von Daten, auf die verwiesen wird.

Referenzen: