Ademais de compartir novas do desenvolvemento de Metarcade, neste blog pretendo compartir cousas que aprendín e continúo a aprender sobre o uso de Godot.
Quizais o uso de @export
para notar que unha variable poda ser modificada dende o editor de maneira visual. De entrada pode valer para equipos grandes nos compañeiros que non programan podan modificar o comportamento do xogo, pero ten moitas outras capacidades para deseñar a arquitectura dun videoxogo.
En todos os casos o recomendado é consultar a documentación de Godot, pero en resumo, podemos exportar variables do seguitne modo:
@export var velocidade: int = 5
@export var outro_nodo: Node
Como no exemplo anterior, na maior parte dos casos necesítase definir o tipo de variable e, opcionalmente, incluír un valor por defecto.
Definir relacións entre nodos
Un uso sinxelo para esta funcionalidade que me axudou enormemente a estruturar o noso proxecto foi usar @export
para definir relacións entre distintos nodos.
Metarcade, como calquera xogo non trivial, ten diferentes “estados de xogo” como explorar, xogar ás máquinas ou dialogar con outros NPC. No noso caso temos definidos os estados como nodos simples que comparten un pai na xerarquía. Como cada estado está asociado a unha interface de usuario distinta, ao principio modeláramolo como na seguinte imaxe:

Diría que se hai un manual de boas prácticas de Godot, mesturar deste xeito na xerarquía nodos de distinto tipo estaría desaconsellado en letras grandes e vermellas. No caso dos nodos de control (en verde) que teñen propiedades semellantes, como neste caso que todos ocupan a mesma porción de pantalla, o mellor é que todos herden do mesmo nodo de control, para así só definir estas propiedades comúns unha vez.

Deste xeito a xerarquía ten máis sentido, pero a conexión entre o estado “Exploring” e os controis “walking_controls” non me resultaba doado de modelar. De entrada trato de non usar variables globais (autoload en Godot) e facer as conexións nun script do nodo pai do seguinte modo:
$StateMachine/Exploring.control_node = $gui_main/walking_controls
Non só é engorroso senón que é moi fraxil ao estragarse xa só se os nodos cambian de nome.
Ata que me percatei de que podía facilmente conectar os diferentes nodos con variables exportadas:
@export var state_controls: Control = null;
Deste xeito, basta con arrastrar cada un dos nodos á propiedade state_controls
do estado.

Tipos complexos
Unha maneira que temos de simplificar o traballo de deseño dos niveis é utilizando variables exportadas en nodos xenéricos como os das máquinas de arcade.

Hai un único nodo que define a máquina e logo exporta variables como o modelo 3D específico, a cor da luz que emite ou a descrición e nome para mostrar nos menús do xogo.
Para isto, no canto de exportar todas as variables por separado, creei un tipo de datos novo que as contén e se ve do seguinte modo no editor:

Non só axuda a organizar as propiedades no menú (que tamén se podería facer con @export_subgroup), senón que me permite enviar a outros nodos a información en conxunto. Un exemplo é o menú que aparece antes de xogar, que indica título, descrición e unha imaxe coa máquina.

Para facer isto basta con crear un novo script, definir un class_name e incluír todas as variables necesarias. Como consello, no canto de herdar de Node
recomendaría usar Resource
como a clase base, xa que non se utilizará ningunha funcionalidade que non a conteña. Hai máis información sobre esto último na documentación.
No meu caso, e para o exemplo das máquinas de arcade, o script final quedou así:
extends Resource
class_name ArcadeMachineData
@export var machine_name: String = "Machine Name"
@export_multiline var machine_desc: String = "Empty description"
@export var machine_difficulty: int = 10
@export var machine_mesh: PackedScene = null
@export var machine_color: Color = Color.WHITE
É importante destacar deste código que tódalas variables teñen un valor por defecto. Isto pode ocorrer unha función _init ou, como enriba, na declaración das variables. De existir algunha variábel sen valor por defecto, a pesar de ser un recurso totalmente válido, o editor de Godot non será capaz de mostralo na interface.
Modificar a escena dende un script
Nalgúns casos vai ser cómodo que os cambios que introducimos a través dun @export
se vexan reflexados na escena no momento de cambialos. Para isto podemos marcar o noso script como @tool
, como explica a documentación.
Deste xeito, se a cor dunha fonte de luz ven definida por unha variable exportada e a cambiamos, poderemos velo directamente na escena mentres a estamos a editar.
Existe un pequeno problema á hora de usar isto para instanciar novas escenas. Cando queremos instanciar unha escena nova, a pesar de facelo na función _ready
, os cambios non serán reflectidos directamente no editor, para iso haberá que modificar a instancia do seguinte xeito:
node.owner = get_tree().edited_scene_root
No meu caso, o código final quedaría así:
@export var data: ArcadeMachineData = ArcadeMachineData.new()
const MESH_NODE_NAME = "arcade-machine"
func _ready():
if Engine.is_editor_hint():
instantiate_configured_mesh()
func instantiate_configured_mesh():
var existing_machine = get_node(MESH_NODE_NAME)
if existing_machine:
existing_machine.queue_free()
var instanced_mesh = data.machine_mesh.instantiate()
add_child(instanced_mesh)
instanced_mesh.name = MESH_NODE_NAME
instanced_mesh.owner = get_tree().edited_scene_root
E deste xeito podo facilmente configurar cómo se verá a escena final.

E ata aquí o que podo dicir de @export
, invítovos a comentar calquera pregunta que teñades, ou ideas sobre como mellorar o meu uso de Godot. Se queredes probar o xogo hai unha pequena demo do que levamos feito ata o de agora en jsmtux.itch.io/metarcade
Deixa una resposta a Autómatas no arcade – Metarcade Bitácora Cancelar a resposta