{"id":56,"date":"2025-04-11T14:35:24","date_gmt":"2025-04-11T12:35:24","guid":{"rendered":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/?p=56"},"modified":"2025-04-11T14:33:30","modified_gmt":"2025-04-11T12:33:30","slug":"usos-de-export-en-godot","status":"publish","type":"post","link":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/2025\/04\/11\/usos-de-export-en-godot\/","title":{"rendered":"Usos de @export en Godot"},"content":{"rendered":"\n<p>Ademais de compartir novas do desenvolvemento de Metarcade, neste blog pretendo compartir cousas que aprend\u00edn e contin\u00fao a aprender sobre o uso de Godot.<\/p>\n\n\n\n<p>Quizais o uso de <code>@export<\/code> para notar que unha variable poda ser modificada dende o editor de maneira visual. De entrada pode valer para equipos grandes nos compa\u00f1eiros que non programan podan modificar o comportamento do xogo, pero ten moitas outras capacidades para dese\u00f1ar a arquitectura dun videoxogo.<\/p>\n\n\n\n<p>En todos os casos o recomendado \u00e9 consultar a <a href=\"https:\/\/docs.godotengine.org\/en\/stable\/tutorials\/scripting\/gdscript\/gdscript_exports.html\">documentaci\u00f3n de Godot<\/a>, pero en resumo, podemos exportar variables do seguitne modo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@export var velocidade: int = 5\n@export var outro_nodo: Node<\/code><\/pre>\n\n\n\n<p>Como no exemplo anterior, na maior parte dos casos neces\u00edtase definir o tipo de variable e, opcionalmente, inclu\u00edr un valor por defecto.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Definir relaci\u00f3ns entre nodos<\/h2>\n\n\n\n<p>Un uso sinxelo para esta funcionalidade que me axudou enormemente a estruturar o noso proxecto foi usar <code>@export<\/code> para definir relaci\u00f3ns entre distintos nodos.<\/p>\n\n\n\n<p>Metarcade, como calquera xogo non trivial, ten diferentes &#8220;estados de xogo&#8221; como explorar, xogar \u00e1s m\u00e1quinas ou dialogar con outros NPC. No noso caso temos definidos os estados como nodos simples que comparten un pai na xerarqu\u00eda. Como cada estado est\u00e1 asociado a unha interface de usuario distinta, ao principio model\u00e1ramolo como na seguinte imaxe:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"338\" height=\"306\" src=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-2.png\" alt=\"\" class=\"wp-image-57\" srcset=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-2.png 338w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-2-300x272.png 300w\" sizes=\"auto, (max-width: 338px) 100vw, 338px\" \/><\/figure>\n\n\n\n<p>Dir\u00eda que se hai un manual de boas pr\u00e1cticas de Godot, mesturar deste xeito na xerarqu\u00eda nodos de distinto tipo estar\u00eda desaconsellado en letras grandes e vermellas. No caso dos nodos de control (en verde) que te\u00f1en propiedades semellantes, como neste caso que todos ocupan a mesma porci\u00f3n de pantalla, o mellor \u00e9 que todos herden do mesmo nodo de control, para as\u00ed s\u00f3 definir estas propiedades com\u00fans unha vez.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"303\" height=\"345\" src=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-3.png\" alt=\"\" class=\"wp-image-58\" srcset=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-3.png 303w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-3-263x300.png 263w\" sizes=\"auto, (max-width: 303px) 100vw, 303px\" \/><\/figure>\n\n\n\n<p>Deste xeito a xerarqu\u00eda ten m\u00e1is sentido, pero a conexi\u00f3n entre o estado &#8220;Exploring&#8221; e os controis &#8220;walking_controls&#8221; non me resultaba doado de modelar. De entrada trato de non usar variables globais (autoload en Godot) e facer as conexi\u00f3ns nun script do nodo pai do seguinte modo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$StateMachine\/Exploring.control_node = $gui_main\/walking_controls<\/code><\/pre>\n\n\n\n<p>Non s\u00f3 \u00e9 engorroso sen\u00f3n que \u00e9 moi fraxil ao estragarse xa s\u00f3 se os nodos cambian de nome.<\/p>\n\n\n\n<p>Ata que me percatei de que pod\u00eda facilmente conectar os diferentes nodos con variables exportadas:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@export var state_controls: Control = null;<\/code><\/pre>\n\n\n\n<p>Deste xeito, basta con arrastrar cada un dos nodos \u00e1 propiedade <code>state_controls<\/code> do estado.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"538\" height=\"93\" src=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-4.png\" alt=\"\" class=\"wp-image-59\" srcset=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-4.png 538w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-4-300x52.png 300w\" sizes=\"auto, (max-width: 538px) 100vw, 538px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Tipos complexos<\/h2>\n\n\n\n<p>Unha maneira que temos de simplificar o traballo de dese\u00f1o dos niveis \u00e9 utilizando variables exportadas en nodos xen\u00e9ricos como os das m\u00e1quinas de arcade.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"507\" src=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-5-1024x507.png\" alt=\"\" class=\"wp-image-60\" srcset=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-5-1024x507.png 1024w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-5-300x148.png 300w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-5-768x380.png 768w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-5.png 1041w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Hai un \u00fanico nodo que define a m\u00e1quina e logo exporta variables como o modelo 3D espec\u00edfico, a cor da luz que emite ou a descrici\u00f3n e nome para mostrar nos men\u00fas do xogo.<\/p>\n\n\n\n<p>Para isto, no canto de exportar todas as variables por separado, creei un tipo de datos novo que as cont\u00e9n e se ve do seguinte modo no editor:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"623\" height=\"601\" src=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-6.png\" alt=\"\" class=\"wp-image-61\" srcset=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-6.png 623w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-6-300x289.png 300w\" sizes=\"auto, (max-width: 623px) 100vw, 623px\" \/><\/figure>\n\n\n\n<p>Non s\u00f3 axuda a organizar as propiedades no men\u00fa (que tam\u00e9n se poder\u00eda facer con @export_subgroup), sen\u00f3n que me permite enviar a outros nodos a informaci\u00f3n en conxunto. Un exemplo \u00e9 o men\u00fa que aparece antes de xogar, que indica t\u00edtulo, descrici\u00f3n e unha imaxe coa m\u00e1quina.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"896\" src=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-7.png\" alt=\"\" class=\"wp-image-62\" srcset=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-7.png 643w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-7-215x300.png 215w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure>\n\n\n\n<p>Para facer isto basta con crear un novo script, definir un <strong>class_name<\/strong> e inclu\u00edr todas as variables necesarias. Como consello, no canto de herdar de <code>Node<\/code> recomendar\u00eda usar <code>Resource<\/code> como a clase base, xa que non se utilizar\u00e1 ningunha funcionalidade que non a conte\u00f1a. Hai m\u00e1is informaci\u00f3n sobre esto \u00faltimo na <a href=\"https:\/\/docs.godotengine.org\/en\/3.4\/tutorials\/best_practices\/node_alternatives.html\">documentaci\u00f3n<\/a>.<\/p>\n\n\n\n<p>No meu caso, e para o exemplo das m\u00e1quinas de arcade, o script final quedou as\u00ed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>extends Resource\nclass_name ArcadeMachineData\n@export var machine_name: String = \"Machine Name\"\n@export_multiline var machine_desc: String = \"Empty description\"\n@export var machine_difficulty: int = 10\n@export var machine_mesh: PackedScene = null\n@export var machine_color: Color = Color.WHITE<\/code><\/pre>\n\n\n\n<p>\u00c9 importante destacar deste c\u00f3digo que t\u00f3dalas variables te\u00f1en un valor por defecto. Isto pode ocorrer unha funci\u00f3n _init ou, como enriba, na declaraci\u00f3n das variables. De existir algunha vari\u00e1bel sen valor por defecto, a pesar de ser un recurso totalmente v\u00e1lido, o editor de Godot non ser\u00e1 capaz de mostralo na interface.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Modificar a escena dende un script<\/h2>\n\n\n\n<p>Nalg\u00fans casos vai ser c\u00f3modo que os cambios que introducimos a trav\u00e9s dun <code>@export<\/code> se vexan reflexados na escena no momento de cambialos. Para isto podemos marcar o noso script como <code>@tool<\/code>, como explica a <a href=\"https:\/\/docs.godotengine.org\/en\/stable\/tutorials\/plugins\/running_code_in_the_editor.html\">documentaci\u00f3n<\/a>.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>Existe un pequeno problema \u00e1 hora de usar isto para instanciar novas escenas. Cando queremos instanciar unha escena nova, a pesar de facelo na funci\u00f3n <code>_ready<\/code>, os cambios non ser\u00e1n reflectidos directamente no editor, para iso haber\u00e1 que modificar a instancia do seguinte xeito:<\/p>\n\n\n\n<pre id=\"codecell23\" class=\"wp-block-code\"><code>node.owner = get_tree().edited_scene_root<\/code><\/pre>\n\n\n\n<p>No meu caso, o c\u00f3digo final quedar\u00eda as\u00ed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@export var data: ArcadeMachineData = ArcadeMachineData.new()\n\nconst MESH_NODE_NAME = \"arcade-machine\"\n\nfunc _ready():\n  if Engine.is_editor_hint():\n  instantiate_configured_mesh()\n\nfunc instantiate_configured_mesh():\n  var existing_machine = get_node(MESH_NODE_NAME)\n  if existing_machine:\n    existing_machine.queue_free()\n  var instanced_mesh = data.machine_mesh.instantiate()\n  add_child(instanced_mesh)\n  instanced_mesh.name = MESH_NODE_NAME\n  instanced_mesh.owner = get_tree().edited_scene_root<\/code><\/pre>\n\n\n\n<p>E deste xeito podo facilmente configurar c\u00f3mo se ver\u00e1 a escena final.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"526\" src=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-8-1024x526.png\" alt=\"\" class=\"wp-image-78\" srcset=\"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-8-1024x526.png 1024w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-8-300x154.png 300w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-8-768x395.png 768w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-8-1536x789.png 1536w, https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-content\/uploads\/sites\/8\/2025\/04\/image-8.png 1999w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>E ata aqu\u00ed o que podo dicir de <code>@export<\/code>, inv\u00edtovos a comentar calquera pregunta que te\u00f1ades, 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 <a href=\"http:\/\/jsmtux.itch.io\/metarcade\" data-type=\"link\" data-id=\"jsmtux.itch.io\/metarcade\">jsmtux.itch.io\/metarcade<\/a><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ademais de compartir novas do desenvolvemento de Metarcade, neste blog pretendo compartir cousas que aprend\u00edn e contin\u00fao 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\u00f1eiros que non programan [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":78,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":3,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"federated","footnotes":""},"categories":[1],"tags":[],"class_list":["post-56","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sen-categoria"],"_links":{"self":[{"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/posts\/56","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/comments?post=56"}],"version-history":[{"count":3,"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/posts\/56\/revisions"}],"predecessor-version":[{"id":79,"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/posts\/56\/revisions\/79"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/media\/78"}],"wp:attachment":[{"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/media?parent=56"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/categories?post=56"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.amarinha.gal\/metarcade_bitacora\/wp-json\/wp\/v2\/tags?post=56"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}