Up to date

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

Tipos principales

Godot tiene una colección rica de clases y plantillas que componen su núcleo, y todo está construido a base de ellas.

Esta fuente las registra en orden.

Definiciones

Godot utiliza los tipos de datos estándar de C99, como uint8_t, uint32_t, int64_t, etc., que en la actualidad son compatibles con todos los compiladores. Reinventar la rueda para estos tipos de datos no es divertido y hace que el código sea más difícil de leer.

En general, no se presta atención para utilizar el tipo de dato más eficiente para una tarea determinada, a menos que se estén usando estructuras o matrices grandes. El tipo de dato int se utiliza en la mayoría del código a menos que sea necesario. Esto se hace porque hoy en día todos los dispositivos tienen al menos un bus de 32 bits y pueden realizar estas operaciones en un solo ciclo. Además, esto hace que el código sea más legible.

Para archivos o tamaños de memoria, se utiliza size_t, que garantiza tener 64 bits.

Para caracteres Unicode, se utiliza CharType en lugar de wchar_t, ya que en muchas arquitecturas wchar_t tiene un tamaño de 4 bytes, donde 2 bytes podrían ser preferibles. Sin embargo, por defecto, esto no ha sido forzado y CharType se mapea directamente a wchar_t.

Referencias:

Modelo de memoria

PC es una arquitectura maravillosa. Las computadoras a menudo tienen gigabytes de RAM, terabytes de almacenamiento y gigahertz de CPU, y cuando una aplicación necesita más recursos, el sistema operativo intercambiará los inactivos. Otras arquitecturas (como móviles o consolas) generalmente son más limitadas.

El modelo de memoria más común es el montón (heap), donde una aplicación solicitará una región de memoria y el sistema operativo subyacente intentará ubicarla en algún lugar y devolverla. Esto suele funcionar de manera óptima y es flexible, pero con el tiempo y el mal uso, puede conducir a la fragmentación.

La segmentación crea lentamente espacios que son demasiado pequeños para la mayoría de las asignaciones comunes, lo que resulta en un desperdicio de memoria. Existe mucha literatura sobre el montón y la segmentación, por lo que este tema no se desarrollará más aquí. Los sistemas operativos modernos utilizan memoria paginada, lo que ayuda a mitigar el problema de la segmentación pero no lo resuelve por completo.

Sin embargo, en muchos estudios y pruebas, se ha demostrado que si se dispone de suficiente memoria y el tamaño máximo de asignación está por debajo de un umbral dado en proporción al tamaño máximo del montón y la proporción de memoria destinada a no utilizarse, la segmentación no será un problema a lo largo del tiempo, ya que se mantendrá constante. En otras palabras, dejar un 10-20% de la memoria libre y realizar todas las asignaciones pequeñas resolverá el problema.

Godot se asegura de que todos los objetos que pueden ser asignados dinámicamente sean pequeños (como máximo unos pocos kb). Pero, ¿qué sucede si una asignación es demasiado grande (como una imagen o geometría de malla o una matriz grande)? En este caso, Godot tiene la opción de utilizar un "pool" de memoria dinámica. Esta memoria debe estar bloqueada para poder acceder a ella, y si una asignación se queda sin memoria, el "pool" se reorganizará y compactará según sea necesario. Dependiendo de las necesidades del juego, el programador puede configurar el tamaño del "pool" de memoria dinámica.

Asignación de memoria

Godot tiene muchas herramientas para rastrear el uso de memoria en un juego, especialmente durante la depuración. Debido a esto, no se deben usar las llamadas regulares a las bibliotecas C y C++. En su lugar, se proporcionan algunas otras.

Para la asignación de memoria de estilo C, Godot proporciona algunos macros:

memalloc()
memrealloc()
memfree()

Estos son equivalentes a los habituales malloc, realloc y free de la biblioteca estándar de C.

Para la asignación de estilo C++, se proporcionan macros especiales:

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

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

que son equivalentes a new, delete, new[] y delete[].

memnew/memdelete también utilizan un poco de magia de C++ y notifican a los objetos justo después de que son creados y justo antes de que sean eliminados.

Para la memoria dinámica, se proporciona la plantilla PoolVector<>. PoolVector es una clase de vector estándar y es muy similar al vector en la biblioteca estándar de C++. Para crear un búfer PoolVector, usa lo siguiente:

PoolVector<int> data;

PoolVector se puede acceder utilizando el operador [] y existen algunos ayudantes para esto:

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

Estas operaciones permiten una lectura y escritura rápida de los PoolVectors y mantienen el bloqueo hasta que salen del ámbito. Sin embargo, los PoolVectors deben usarse para operaciones de memoria pequeñas y dinámicas, ya que read() y write() son demasiado lentas para una gran cantidad de accesos.

Referencias:

Contenedores

Godot también proporciona un conjunto de contenedores comunes:

  • Vector

  • Lista

  • Establecer

  • Mapa

They aim to be as minimal as possible, as templates in C++ are often inlined and make the binary size much fatter, both in debug symbols and code. List, Set and Map can be iterated using pointers, like this:

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

La clase Vector<> también tiene algunas características interesantes:

  • Realiza "copia en escritura" (copy-on-write), lo que significa que hacer copias de ella es barato siempre y cuando no sean modificadas.

  • Además, admite multi-hilos mediante el uso de operaciones atómicas en el contador de referencias.

Referencias:

Cadena

Godot también proporciona una clase String. Esta clase tiene una gran cantidad de funciones, soporte completo para Unicode en todas las operaciones (como operaciones de mayúsculas y minúsculas) y análisis/extracción de utf8, así como funciones de ayuda para conversiones y visualización.

Referencias:

Nombre de cadena

Los StringNames son similares a Strings, pero son únicos. Al crear un StringName a partir de una cadena, se obtiene un puntero interno único para todas las cadenas iguales. Los StringNames son útiles para utilizar cadenas como identificadores, ya que compararlos es básicamente comparar un puntero.

La creación de un StringName (especialmente uno nuevo) es lenta, pero la comparación es rápida.

Referencias:

Tipos Matemáticos

En el directorio core/math de Godot, hay varios tipos de matemáticas lineales disponibles.

Referencias:

Ruta del nodo

Este es un tipo de dato especial utilizado para almacenar rutas en un árbol de escena y hacer referencia a ellas de manera rápida.

Referencias:

RID

Los RID son identificadores de recursos. Los servidores los utilizan para hacer referencia a los datos almacenados en ellos. Los RID son opacos, lo que significa que los datos a los que hacen referencia no se pueden acceder directamente. Los RID son únicos, incluso para diferentes tipos de datos referenciados.

Referencias: