Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Die Klasse "Object"

Siehe auch

Diese Seite beschreibt die C++-Implementierung von Objects in Godot. Suchen Sie nach der Object-Klassenreferenz? Have a look here.

Allgemeine Definition

Object ist die Basisklasse für fast alles. Die meisten Klassen in Godot erben direkt oder indirekt davon. Objects bieten Reflexions- und bearbeitbare Propertys, und für deren Deklaration muss ein einziges Makro wie dieses verwendet werden:

class CustomObject : public Object {

    GDCLASS(CustomObject, Object); // this is required to inherit
};

Dadurch erhalten Objects viele Funktionen, wie zum Beispiel:

obj = memnew(CustomObject);
print_line("Object class: ", obj->get_class()); // print object class

obj2 = Object::cast_to<OtherClass>(obj); // converting between classes, this also works without RTTI enabled.

Referenzen:

Ein Object registrieren

ClassDB ist eine statische Klasse, welche die gesamte Liste der von Object geerbten registrierten Klassen sowie dynamische Bindings an alle Methoden-Propertys und Integer-Konstanten enthält.

Klassen werden registriert durch Aufrufen von:

ClassDB::register_class<MyCustomClass>()

Durch die Registrierung kann die Klasse durch Skripte oder Code instanziiert, oder beim Deserialisieren erneut erstellt werden.

Die Registrierung als virtuell ist die gleiche, aber sie kann nicht instanziiert werden.

ClassDB::register_virtual_class<MyCustomClass>()

Von Objects abgeleitete Klassen können die statische Funktion static void _bind_methods() überschreiben. Wenn eine Klasse registriert ist, wird diese statische Funktion aufgerufen, um alle Object-Methoden, Propertys, Konstanten usw. zu registrieren. Sie wird nur einmal aufgerufen. Wenn eine von Object abgeleitete Klasse instanziiert, aber nicht registriert wurde, wird sie automatisch als virtuell registriert.

In _bind_methods gibt es ein paar Dinge, die getan werden können. Das Registrieren von Funktionen ist eines davon:

ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name", "arg3name"), &MyCustomType::method);

Default values for arguments can be passed as parameters at the end:

ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name", "arg3name"), &MyCustomType::method, DEFVAL(-1), DEFVAL(-2)); // Default values for arg2name (-1) and arg3name (-2).

Default values must be provided in the same order as they are declared, skipping required arguments and then providing default values for the optional ones. This matches the syntax for declaring methods in C++.

D_METHOD ist ein Makro, das "methodname" zur Steigerung der Effizienz in einen StringName konvertiert. Argumentnamen werden zur Selbstbeobachtung verwendet, aber beim Kompilieren beim Release werden sie vom Makro ignoriert, sodass die Strings nicht verwendet und nicht optimiert werden.

Weitere Beispiele finden Sie unter _bind_methods von Control oder Object.

Wenn nur Module und Funktionen hinzugefügt werden, von denen nicht erwartet wird, dass sie so gründlich dokumentiert werden, kann das Makro D_METHOD() ignoriert und einen String, der den Namen übergibt, kann der Kürze halber übergeben werden.

Referenzen:

Konstanten

Klassen haben oft Enums wie:

enum SomeMode {
   MODE_FIRST,
   MODE_SECOND
};

Damit diese beim Binding an Methoden funktionieren, muss die Aufzählung als nach int konvertierbar deklariert werden. Dazu wird ein Makro bereitgestellt:

VARIANT_ENUM_CAST(MyClass::SomeMode); // now functions that take SomeMode can be bound.

Die Konstanten können auch innerhalb von _bind_methods gebunden werden, indem Sie Folgendes verwenden:

BIND_CONSTANT(MODE_FIRST);
BIND_CONSTANT(MODE_SECOND);

Propertys (set/get)

Objects exportieren Propertys, Propertys sind für Folgendes nützlich:

  • Serialisierung und Deserialisierung des Objects.

  • Erstellen einer Liste editierbarer Werte für die vom Object abgeleitete Klasse.

Propertys werden normalerweise durch die Klasse PropertyInfo() definiert und konstruiert als:

PropertyInfo(type, name, hint, hint_string, usage_flags)

Zum Beispiel:

PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "0,49,1", PROPERTY_USAGE_EDITOR)

Dies ist eine Integer-Property mit dem Namen "amount". Die Variable "hint" ist eine Range und die Range reicht von 0 bis 49 in Schritten von 1 (Integer). Sie kann nur für den Editor verwendet werden (Wert visuell bearbeiten), wird jedoch nicht serialisiert.

Ein weiteres Beispiel:

PropertyInfo(Variant::STRING, "modes", PROPERTY_HINT_ENUM, "Enabled,Disabled,Turbo")

Dies ist eine String-Property, die jede beliebigen String annehmen kann, aber der Editor wird nur die definierten Hints-Strings zulassen. Da keine Verwendungsflags angegeben wurden, sind die Default-Flags PROPERTY_USAGE_STORAGE und PROPERTY_USAGE_EDITOR.

In object.h sind viele Hints und Verwendungsflags verfügbar, schauen Sie mal rein.

Propertys können auch wie C#-Propertys funktionieren und von einem Skript aus über Indizierung aufgerufen werden, aber von dieser Verwendung wird im Allgemeinen abgeraten, da die Verwendung von Funktionen aus Gründen der Lesbarkeit vorzuziehen ist. Viele Eigenschaften sind auch an Kategorien gebunden, wie z.B. "Animation/Frame", was eine Indizierung ebenfalls unmöglich macht, es sei denn, man verwendet den Operator [].

Aus _bind_methods() können Propertys erstellt und gebunden werden, solange set/get-Funktionen vorhanden sind. Beispiel:

ADD_PROPERTY(PropertyInfo(Variant::INT, "amount"), "set_amount", "get_amount")

Dadurch wird die Property mit Hilfe des Setters und des Getters erstellt.

Binding von Propertys mit _set/_get/_get_property_list

Ein zusätzliches Verfahren zum Erstellen von Propertys besteht, wenn mehr Flexibilität gewünscht wird (d.h. Hinzufügen oder Entfernen von Propertys im Kontext).

Die folgenden Funktionen können in einer von Object abgeleiteten Klasse überschrieben werden. Sie sind NICHT virtuell. Machen Sie sie NICHT virtuell. Sie werden bei jeder Überschreibung aufgerufen und die vorherigen Funktionen werden nicht ungültig gemacht (mehrstufiger Aufruf).

protected:
     void _get_property_list(List<PropertyInfo> *r_props) const;      // return list of properties
     bool _get(const StringName &p_property, Variant &r_value) const; // return true if property was found
     bool _set(const StringName &p_property, const Variant &p_value); // return true if property was found

Dies ist auch etwas weniger effizient, da p_property mit den gewünschten Namen in serieller Reihenfolge verglichen werden muss.

Dynamisches Casting

Godot bietet zum Beispiel dynamisches Casting zwischen von Object abgeleiteten Klassen an:

void somefunc(Object *some_obj) {

     Button *button = Object::cast_to<Button>(some_obj);
}

Wenn die Umwandlung fehlschlägt, wird NULL zurückgegeben. Dieses System verwendet RTTI, funktioniert aber auch einwandfrei (wenn auch etwas langsamer), wenn RTTI deaktiviert ist. Dies ist nützlich auf Plattformen, auf denen eine kleine Binärgröße ideal ist, z.B. HTML5 oder Konsolen (mit geringem Speicher).

Signale

Für Objects kann eine Reihe von Signalen definiert werden (ähnlich wie bei Delegates in anderen Sprachen). Dieses Beispiel zeigt, wie man sich mit ihnen verbindet:

obj->connect(<signal>, target_instance, target_method)
// for example:
obj->connect("enter_tree", this, "_node_entered_tree")

Die Methode _node_entered_tree muss bei der Klasse mit ClassDB::bind_method registriert werden (siehe oben).

Das Hinzufügen von Signalen zu einer Klasse erfolgt in _bind_methods, z.B. mit dem Makro ADD_SIGNAL:

ADD_SIGNAL(MethodInfo("been_killed"))

Benachrichtigungen

Alle Objects in Godot haben eine _notification-Methode, die es ihnen ermöglicht, auf Engine-Level-Callbacks zu reagieren, die sich auf sie beziehen können. Weitere Informationen können auf der Seite Benachrichtigungen in Godot gefunden werden.

Referenzen

RefCounted erbt von Object und enthält einen Reference Count. Sie ist die Basis für Objekttypen, die mit Reference Counting getrackt werden. Ihre Deklaration muss mit dem Ref<>-Template erfolgen. Zum Beispiel:

class MyReference: public RefCounted {
    GDCLASS(MyReference, RefCounted);
};

Ref<MyReference> myref(memnew(MyReference));

myref wird als Referenz gezählt. Es wird freigegeben, wenn keine Ref<>-Templates mehr darauf verweisen.

Referenzen:

Ressourcen

Resource erbt von Reference, sodass alle Ressourcen als Referenz gezählt werden. Ressourcen können optional einen Pfad enthalten, der auf eine Datei auf der Festplatte verweist. Dies kann mit resource.set_path(path) eingestellt werden, was normalerweise vom Ressource-Loader durchgeführt wird. Keine zwei verschiedenen Ressourcen können denselben Pfad haben. Wenn Sie dies versuchen, wird ein Fehler angezeigt.

Ressourcen ohne Pfad sind ebenfalls in Ordnung.

Referenzen:

Ressourcen laden

Ressourcen können mit der ResourceLoader-API wie folgt geladen werden:

Ref<Resource> res = ResourceLoader::load("res://someresource.res")

Wenn zuvor eine Referenz auf diese Ressource geladen wurde und sich im Speicher befindet, gibt der Ressource-Loader diese Referenz zurück. Dies bedeutet, dass nur eine Ressource gleichzeitig aus einer Datei geladen werden kann, auf die auf der Festplatte referenziert wird.

  • resourceinteractiveloader (TODO)

Referenzen:

Ressourcen speichern

Das Speichern einer Ressource kann mit der Resource Saver-API erfolgen:

ResourceSaver::save("res://someresource.res", instance)

Die Instanz wird gespeichert und Unterressourcen, die einen Pfad zu einer Datei haben, werden als Verweis auf diese Ressource gespeichert. Unterressourcen ohne Pfad werden mit der gespeicherten Ressource gebündelt und mit Sub-IDs versehen, wie res://someresource.res::1. Dies hilft auch, sie beim Laden zu cachen.

Referenzen: