Sean bienvenidos a mi nuevo post. Hoy hablaremos de como atraves del AutoLoad podremos intercambiar escenas y transferir informacion entre ellas. Como vimos hasta ahora, el sistema de escenas es fuerte y robusto pero este contiene algunos inconvenientes, los cuales pasaremos a enlistar:

  • No hay un lugar en comun para almacenar informacion requerida por mas de una escena (p.e. los items del jugador)
  • Es posible cargar y descargar escenas como childrens para almacenar una informacion en comun entre todos los childrens, pero no es posible correr esas escenas por ellas mismas y que funcionen correctamente.
  • Podemos guardar informacion en el path user://, hablamos en este post, y cargar cuando inicia una escena pero esto nos traera problemas de performance porque el juego estara constantemente accediendo al disco.

Sin embargo vamos a necesitar crear partes de escenas que:

  • Esten siempre cargadas, no importa cual escena desde el editor.
  • Poder almacenar variables globales, como informacion del jugador, items, dinero, etc y compartir informacion entre escenas
  • Poder manejar el intercambio de escenas y las transiciones.
  • Actuar como un “semifallo” (singleton), desde que GDscript no soporta mas variables globales por diseño.

AutoLoad en nodos y scripts satisface estas necesidades.

AutoLoad

Se puede usar AutoLoad para cargar escena, o un script heredero de un nodo. Para crear un AutoLoad debemos ir a Proyecto -> Ajustes de proyectos, ahi debemos ir a la solapa AutoLoad, por cada entrada debemos asignarle un nombre, lo cual es usado como nombre del nodo, y este nodo es siempre agregado al root viewport ante que cualquier otra escena sea cargada.

singleton
Fuente: docs.godotengine.org

Supongamos la creacion de un singleton llamado playervariables, cualquier nodo puede acceder de la siguiente forma:

var player_vars = get_node(“/root/playervariables”)
player_vars.health

O de una forma mas simple:

playervariables.health

Pasemos a ver como crear una transferidor de escena propio, para empezar vamos a descargar este archivo autoload, luego crearemos nuestro proyecto. En el editor de godot hacemos click en proyecto nuevo, donde nos aparecera esta pantalla

godot00

Ingresaremos el nombre de nuestro proyecto, por ejemplo AutoLoad, vamos a examinar y seleccionaremos la carpeta de nuestros proyectos, como pueden ver en la imagen esta nos dira que no esta vacia pero una vez llegado hasta ahi eligen Crear Carpeta y nos queda algo asi

godot01

Como ven ahora tenemos luz verde y seguir para adelante, le damos a crear y editar donde nos abrira nuestro proyecto. Al principio tendremos estos elementos (assets)

godot02

Si abrimos el archivo descargado y extraemos todos los archivos contenidos en el mismo dentro de la carpeta de nuestro proyecto sucedera esto

godot03

Ahora procederemos a abrir nuestras escenas, para poder ver nuestras escenas pero van a tener el siguiente error cuando abran el archivo scene_a.scn

godot04

Le dan a Abrir de todos modos, y se abre correctamente. Lo mismo sucede con el archivo scene_b.scn

godot05

Le dan de nuevo a Abrir de todos modos y funciona correctamente, con las dos escenas arregladas por el editor de godot podemos probar de ejecutarlo y ver hasta donde esta operativa, si le damos a ejecutar o presionamos F5 nos mostrara el siguiente mensaje

godot06

Esto es porque no definimos una escena principal, nos abrira un cuadro con todos los elementos del proyecto y elegiremos el archivo scene_a.scn, una vez seleccionado se nos abrira el proyecto y quedara asi

Hasta aca, establecimos las bases de nuestro proyecto y tambien corrigiendo algunos errores, ahora deberemos crear un script global para la opcion de AutoLoad, para esto elegiremos entre las opciones script, como se ve en la siguiente imagen, y luego archivo-> nuevo

godot08

Se nos abrira el siguiente cuadro, y lo unico que completaremos sera el nombre del archivo en la opcion Ruta, con el nombre global.gd

godot09

Lo dejan tal cual como se ve en la imagen y le dan crear, una vez creado deberemos asociar nuevamente los scripts, para esto debemos elegir la escena correspondiente, por ejemplo scene_a.scn, y en la solapa Escena, eligiendo el nodo Panel llamado scene_a, nos aparecera el boton para agregarle un script

godot15

Una vez clickeado nos aparecera el siguiente cuadro de dialogo

godot16

Donde pueden ver al archivo de script ya ingresado en Ruta, lo dejan todo como esta y eligen cargar, lo mismo deben hacer con el archivo scene_b.scn, una vez finalizado nos deberia quedar una imagen como la siguiente

godot10

Ya tenemos nuestro script global creado ahora deberiamos asociarlo a AutoLoad, para esto vamos a Proyectos->Ajustes de proyectos

godot07

Luego seleccionaremos la solapa AutoLoad y deberemos hacer click donde esta el circulo rojo

godot11

Una vez hecho esto nos aparecera el siguiente cuadro de dialogo donde elegiremos el script creado por nosotros, global.gd

godot12

Una vez elegido, nos quedara de esta forma la solapa de AutoLoad y clickeamos en Añadir

godot13

Una vez añadido queda asi

godot14

Con esto concluimos el AutoLoad, de ahora en adelante cada vez que compilemos el archivo global.gd se cargara automaticamente. Ahora procederemos a completar nuestros scripts para finalizar con nuestra tarea, pasemos a los scripts:

global.gd

extends Node

var current_scene = null

func _ready():
 var root = get_tree().get_root()
 current_scene = root.get_child( root.get_child_count() -1 )

func goto_scene(path):
 call_deferred(“_deferred_goto_scene”,path)

func _deferred_goto_scene(path):
 current_scene.free()
 var s = ResourceLoader.load(path)
 current_scene = s.instance()
 get_tree().get_root().add_child(current_scene)
 get_tree().set_current_scene( current_scene )

Este va a ser nuestro script principal porque va a almacenar la funcion para cambiar de escena, fundamental al principio de nuestro script el extends debe ser sobre Node. Luego crearemos la variable current_scene, la cual se encargara la escena actual pero ahora va a tener un valor null. En la funcion _ready() vamos a crear una variable llamada root, en la cual almacenaremos la raiz de nuestro arbol de escenas, y a current_scene le asignaremos el valor de la cantidad de childs restandole uno, la siguiente funcion sera la utilizada en el resto de los scripts, esta es goto_scene(path) donde path sera el valor de la escena a ir pero en esta funcion solo llamaremos a la funcion encargada de hacer el verdadero cambio, _deferred_goto_scene(path). Nuestra primera linea nos libera a current_scene, no se preocupen no hay ningun riesgo aqui, luego crearemos una variable llamada s donde cargaremos el recurso informado en path, una vez cargado setearemos este recurso como instancia dentro current_scene, para finalmente agregarlo como child en la siguiente linea y por ultimo definirlo como la escena actual. Con esto finalizamos el script global.gd, el cual sera el encargado de pasar de una escena a la otra, procedamos con los otros scripts restantes.

scene_a.gd

func _on_goto_scene_pressed():
 get_node(“/root/global”).goto_scene(“res://scene_b.scn”)

scene_b.gd

func _on_goto_scene_pressed():
 get_node(“/root/global”).goto_scene(“res://scene_a.scn”)

Como pueden ver son exactamente iguales pero la diferencia esta el recurso a llamar, estan invertidos, la escena A llama al archivo scene_b.scn y la escena B al archivo scene_a.scn pero la funcion para ir a la escena es misma porque es la almacenada en global.gd y la misma es cargada a traves del AutoLoad, observen como el valor entre comillas (“) es el seteador de path para el archivo global.gd, si todo sale bien deberia quedar algo como este video

Si lograste lo mismo a lo del video, enhorabuena por haber logrado el objetivo. En resumen, esto es util para los momentos en los cuales pasamos por ejemplo de una pantalla a la otra, o cambiamos de nivel y necesitamos mantener todos los datos del jugador exactamente iguales, si bien esto se puede lograr manteniendo los mismos en el disco, a traves del recurso user://, cuando es mucha informacion nos traera el inconveniente de la performance entre escena y escena, pudiendo estar todo almacenado en memoria haciendolo mucho mas fluido. Por ahora, voy a descansar un poco de godot, y me centrare en otros lenguajes proximos a subir, por ejemplo terminar con C++, finalizar con mysql, empezar con C# y Android pero igualmente muy pronto retomaremos con godot para en algun momento poder tener nuestro primer juego profesional. Espero les haya sido util, nos vemos en el proximo post.

Anuncios