Up to date

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

Usando el Árbol de Escenas

Introducción

En tutoriales previos, todo giraba en torno al concepto de nodos. Las escenas son simplemente una colección de nodos. Ellas se activan una vez que entran al árbol de escenas.

MainLoop

La forma en la cual Godot funciona internamente es la siguiente. Existe la clase OS<class_OS, la cual es la única instancia que corre desde el principio. Posteriormente son cargados todos los controladores, servidores, lenguajes de scripting, sistema de escenas, etc.

Una vez finalizada la inicialización, OS necesita que se le suministre un MainLoop para que se ejecute. Hasta este punto, todo esto está funcionando internamente (puedes comprobar el archivo main/main.cpp en el código fuente si alguna vez estás interesado en ver cómo funciona internamente).

El programa del usuario o juego, comienza en el MainLoop. Esta clase tiene algunos métodos, para inicialización, inactivo (devolución de llamada sincronizada por el marco), fijo (devolución de llamada sincronizada por la física) y entrada. De nuevo, este es de bajo nivel y cuando creas juegos en Godot, escribir tu propio MainLoop tiene poco sentido.

Árbol de Escenas

Una de las maneras de explicar cómo funciona Godot es que es un motor de juegos de alto nivel sobre un middleware de bajo nivel.

El sistema de escenas es el motor del juego, mientras que la clase OS y los servidores son la API de bajo nivel.

El sistema de escenas provee al SO su propio bucle principal, SceneTree. Este es automáticamente instanciado y configurado cuando se ejecuta una escena, no es necesario ningún trabajo extra.

Es necesario saber que esta clase existe porque tiene algunos usos importantes:

  • Contiene el Viewport raíz, al cual se añade una escena hija cuando se abre por primera vez, para ser parte del Árbol de Escenas (más información a continuación).

  • Contiene información sobre los grupos y dispone de los medios para llamar a todos los nodos de un grupo u obtener una lista de ellos.

  • Contiene alguna funcionalidad de estado global, como configurar el modo de pausa o salir del proceso.

Cuando un nodo es parte del Árbol de Escenas, el singleton SceneTree puede obtenerse simplemente llamando Node.get_tree().

Viewport raíz

El Viewport raíz está siempre en la parte superior de la escena. Desde un nodo, se puede obtener de dos maneras diferentes:

get_tree().root # Access via scene main loop.
get_node("/root") # Access via absolute path.

Este nodo contiene el viewport principal. Cualquier cosa hija de un Viewport es dibujado en su interior por defecto, toma sentido entonces que el nodo principal sea siempre uno de este tipo, de otro modo no se podría dibujar nada en pantalla.

Mientras que se pueden crear otros viewports en la escena (para obtener resultados en pantalla dividida, etc.), ésta es la única que nunca es creada por el usuario. Se crea automáticamente dentro de SceneTree.

Árbol de escenas

Cuando un nodo es conectado, directa o indirectamente, al viewport raíz, se convierte en parte del árbol de escenas.

Esto significa que, como se explicó en tutoriales anteriores, los autoguardados recibirán las devoluciones de llamada _enter_tree() y _ready() (así como _exit_tree()).

../../_images/activescene.webp

Cuando los nodos entran en el Árbol de Escenas, se activan. Tienen acceso a todo lo que necesitan para procesar, obtener entradas, mostrar 2D y 3D, notificaciones, reproducir sonido, etc. Cuando se remueven del árbol de escenas, pierden acceso a todas esas funcionalidades.

Orden del árbol

Most node operations in Godot, such as drawing 2D, processing, or getting notifications are done in tree order, or top to bottom as seen in the editor (also known as pre-order traversal):

../../_images/toptobottom.webp

For example, the top node in a scene has its _process() function called first, then the node below it has its _process() function called, then the node below that and so on.

An important exception is the _ready() function: each parent node has its _ready() function called only after all its child nodes have their _ready() functions called, so that the parent knows its children are completely ready to be accessed. This is also known as post-order traversal. In the above image, NameLabel would be notified first (but only after its children, if it had any!), followed by Name, etc., and Panel would be notified last.

The order of operations can also be overridden using the process_priority node property. Nodes with a lower number are called first. For example, nodes with the priorities "0, 1, 2, 3" would be called in that order from left to right.

"Activación" entrando en el Árbol de escenas

  1. Una escena es cargada desde disco o creada mediante scripting.

  2. The root node of that scene (only one root, remember?) is added as either a child of the "root" Viewport (from SceneTree), or to any of its descendants.

  3. Every node of the newly added scene will receive the "enter_tree" notification ( _enter_tree() callback in GDScript) in top-to-bottom order (pre-order traversal).

  4. Every node will receive the "ready" notification ( _ready() callback in GDScript) for convenience, once all its children have received the "ready" notification (post-order traversal).

  5. Cuando se elimina una escena (o parte de ella), reciben la notificación "exit scene" ( callback _exit_tree() en GDScript) en orden ascendente.

Cambiando la escena actual

After a scene is loaded, you may want to change this scene for another one. One way to do this is to use the SceneTree.change_scene_to_file() function:

func _my_level_was_completed():
    get_tree().change_scene_to_file("res://levels/level2.tscn")

Rather than using file paths, one can also use ready-made PackedScene resources using the equivalent function SceneTree.change_scene_to_packed(PackedScene scene):

var next_scene = preload("res://levels/level2.tscn")

func _my_level_was_completed():
    get_tree().change_scene_to_packed(next_scene)

These are quick and useful ways to switch scenes but have the drawback that the game will stall until the new scene is loaded and running. At some point in the development of your game, it may be preferable to create proper loading screens with progress bar, animated indicators or threaded (background) loading. This must be done manually using Singletons (Autoload) and Carga en segundo plano.