Up to date

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

Clase Object

Ver también

Esta página describe la implementación en C++ de los objetos en Godot. ¿Buscas la referencia de la clase Object? Échale un vistazo aquí.

Definición General

Object es la clase base para casi todo. La mayoría de las clases en Godot heredan directa o indirectamente de ella. Los Object proporcionan reflexión y propiedades editables, y declararlos es cuestión de usar una sola macro como esta:

class CustomObject : public Object {

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

Esto agrega muchas funcionalidades a Objects. Por ejemplo:

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.

Referencias:

Registrando un Object

ClassDB es una clase estática que contiene la lista completa de clases registradas que heredan de Object, así como enlaces dinámicos a todos sus métodos, propiedades y constantes enteras.

Las clases se registran llamando a:

ClassDB::register_class<MyCustomClass>()

Registrarla permitirá que la clase se instancie mediante scripts, código o al crearlos nuevamente al deserializar.

Registrarla como virtual es lo mismo, pero no se puede instanciar.

ClassDB::register_virtual_class<MyCustomClass>()

Las clases derivadas de Object pueden sobrescribir la función estática static void _bind_methods(). Cuando se registra una clase, esta función estática se llama para registrar todos los métodos, propiedades, constantes, etc., del objeto. Solo se llama una vez. Si se instancia una clase derivada de Object pero no se ha registrado, se registrará automáticamente como virtual.

Dentro de _bind_methods, hay algunas cosas que se pueden hacer. Una de ellas es registrar funciones:

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 es una macro que convierte "methodname" en un StringName para mejorar la eficiencia. Los nombres de los argumentos se utilizan para la introspección, pero al compilar en modo de lanzamiento, la macro los ignora, por lo que las cadenas no se utilizan y se optimizan para que desaparezcan.

Puedes revisar el método _bind_methods de las clases Control u Object para ver más ejemplos.

Si solo estás agregando módulos y funcionalidades que no se espera que estén documentadas en detalle, el macro D_METHOD() puede ser ignorado de forma segura y simplemente puedes pasar un string con el nombre del método para mayor concisión.

Referencias:

Constantes

Las clases a menudo tienen enumeraciones como esta:

enum SomeMode {
   MODE_FIRST,
   MODE_SECOND
};

For these to work when binding to methods, the enum must be declared convertible to int. A macro is provided to help with this:

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

Las constantes también se pueden vincular dentro de _bind_methods, usando:

BIND_CONSTANT(MODE_FIRST);
BIND_CONSTANT(MODE_SECOND);

Propiedades (set/get)

Los objetos exportan propiedades, las propiedades son útiles para lo siguiente:

  • Serializar y deserializar el objeto.

  • Crear una lista de valores editables para la clase derivada de Object.

Properties are usually defined by the PropertyInfo() class and constructed as:

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

Por ejemplo:

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

This is an integer property named "amount". The hint is a range, and the range goes from 0 to 49 in steps of 1 (integers). It is only usable for the editor (editing the value visually) but won't be serialized.

Otro ejemplo:

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

Esta es una propiedad de string, puede tomar cualquier string pero el editor sólo permitirá los que estén definidos como hint. Puesto que no se especificó ningún indicador de uso, los valores por defecto son PROPERTY_USAGE_STORAGE y PROPERTY_USAGE_EDITOR.

Hay muchas sugerencias (hints) y banderas de uso disponibles en "object.h", dales una revisión.

Las propiedades también pueden funcionar como propiedades de C# y accederse desde un script utilizando el indexado, pero este uso generalmente no se recomienda, ya que se prefiere usar funciones para mejorar la legibilidad. Muchas propiedades también están vinculadas con categorías, como por ejemplo "animation/frame", lo que también hace que el indexado sea imposible a menos que se utilice el operador [].

Desde _bind_methods(), las propiedades pueden ser creadas y enlazadas siempre y cuando existan funciones de configuración y obtención (set/get). Ejemplo:

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

Esto crea la propiedad utilizando el setter y el getter.

La vinculación de propiedades utilizando _set/_get/_get_property_list

Existe un método adicional para crear propiedades cuando se desea más flexibilidad (por ejemplo, agregar o eliminar propiedades en un contexto).

Las siguientes funciones pueden ser sobreescritas en una clase derivada de Object, NO las hagas virtuales, son llamadas para cada sobrescritura y las versiones anteriores no se invalidan (llamada multinivel).

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

Esto también es un poco menos eficiente ya que p_property debe ser comparado con los nombres deseados en orden serial.

Casteo dinámico

Godot proporciona el casteo dinámico entre clases derivadas de Object, por ejemplo:

void somefunc(Object *some_obj) {

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

Si el casteo falla, se devuelve NULL. Este sistema utiliza RTTI, pero también funciona bien (aunque un poco más lento) cuando RTTI está deshabilitado. Esto es útil en plataformas donde un tamaño binario pequeño es ideal, como HTML5 o consolas (con una huella de memoria baja).

Señales

Objects can have a set of signals defined (similar to Delegates in other languages). This example shows how to connect to them:

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

El método _node_entered_tree debe ser registrado en la clase utilizando ClassDB::bind_method (explicado anteriormente).

Agregar señales a una clase se hace en _bind_methods, utilizando el macro ADD_SIGNAL, por ejemplo:

ADD_SIGNAL(MethodInfo("been_killed"))

Notificaciones

All objects in Godot have a _notification method that allows it to respond to engine level callbacks that may relate to it. More information can be found on the Notificaciones en Godot page.

Referencias

RefCounted inherits from Object and holds a reference count. It is the base for reference counted object types. Declaring them must be done using Ref<> template. For example:

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

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

myref es un objeto con conteo de referencias. Se liberará cuando ya no haya más plantillas Ref<> apuntando a él.

Referencias:

Recursos

Resource inherits from Reference, so all resources are reference counted. Resources can optionally contain a path, which reference a file on disk. This can be set with resource.set_path(path), though this is normally done by the resource loader. No two different resources can have the same path; attempting to do so will result in an error.

Los recursos sin una ruta también son aceptables.

Referencias:

Cargando un recurso

Los recursos se pueden cargar con la API ResourceLoader, de esta manera:

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

Si se ha cargado previamente una referencia a ese recurso y está en memoria, el cargador de recursos devolverá esa referencia. Esto significa que solo puede haber un recurso cargado desde un archivo referenciado en disco al mismo tiempo.

  • resourceinteractiveloader (TODO)

Referencias:

Guardando un recurso

Guardar un recurso se puede hacer utilizando la API del salvador de recursos:

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

The instance will be saved, and sub resources that have a path to a file will be saved as a reference to that resource. Sub resources without a path will be bundled with the saved resource and assigned sub-IDs, like res://someresource.res::1. This also helps to cache them when loaded.

Referencias: