CommunityProgramación y desarrollogithub.com

ziva-sh/organización-de-escenas-en-godot

Organiza proyectos de Godot 4 para que las escenas sean reutilizables y las referencias no se rompan: cuándo crear una escena, un script o un recurso, instanciación con @export PackedScene, preload y load, acceso a nodos con @onready y %UniqueName, orden de _ready, grupos, autoloads, class_name y UIDs de recursos con archivos .uid añadidos en Godot 4.4, incluyendo cómo mover o renombrar archivos de forma segura.

¿Qué es organización-de-escenas-en-godot?

Este skill proporciona una guía completa para organizar proyectos en Godot 4, asegurando que las escenas se mantengan reutilizables y las referencias no se rompan. Explica las diferencias fundamentales entre escenas (`.tscn`), scripts (`.gd`) y scripts de recursos (`extends Resource`), y cuándo usar cada uno. Incluye patrones de instanciación con `@export PackedScene`, `preload()` y `load()`, así como técnicas para encontrar nodos usando `$`, `%UniqueName`, `get_node_or_null()` y el ciclo de vida `@onready` y `_ready()`. También cubre grupos, autoloads, `class_name` y el manejo de UIDs y archivos `.uid`, especialmente importantes desde Godot 4.4. El skill es útil para cualquier desarrollador que trabaje con Godot 4, ya sea en la creación de nuevas escenas o scripts, al decidir cómo los nodos se encuentran entre sí, al agregar estado global o un bus de eventos, o al mover o renombrar archivos de forma segura. Funciona en cualquier plataforma que admita Godot 4 y está diseñado para ser utilizado con asistentes de IA como Claude Code, Cursor o Codex.

Compatible con~Claude Code~Codex CLI~Cursor
Part ofMobile
npx skills add https://github.com/ziva-sh/godot-skills/tree/HEAD/skills/godot-scene-organization

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Organización de escenas en Godot 4

Escena, script o recurso

  • Escena (.tscn): un árbol reutilizable de nodos con sus propios recursos: un jugador, un enemigo, un objeto recogible, un panel de UI, un nivel. Cualquier cosa que coloques más de una vez o que quieras ejecutar sola (F6) es una escena.
  • Script (.gd): comportamiento adjunto a un nodo. Adjúntalo a la raíz de la escena que controla, no a un padre que accede a ella.
  • Script de recurso (extends Resource con class_name): datos sin un nodo, como estadísticas de objetos, definiciones de oleadas o datos de guardado, editables en el Inspector y guardados como .tres.

Una escena debería funcionar al ejecutarse por sí sola. Si necesita algo del exterior (un objetivo, un padre de generación), exponlo con @export o una señal en lugar de cadenas de get_parent().

Instanciación de escenas

extends Node2D

@export var enemy_scene: PackedScene
@export var spawn_parent: Node2D


func spawn_enemy(at: Vector2) -> void:
	var enemy := enemy_scene.instantiate() as Node2D
	enemy.position = at
	spawn_parent.add_child(enemy)


func load_level(path: String) -> void:
	var packed := load(path) as PackedScene
	if packed == null:
		push_error("Nivel no encontrado: " + path)
		return
	get_tree().change_scene_to_packed(packed)
  • @export var x: PackedScene se configura en el Inspector y sobrevive a movimientos de archivos, porque la escena almacena la referencia.
  • const BULLET := preload("res://bullet.tscn") se resuelve en tiempo de análisis: un archivo faltante es un error de análisis (Preload file "res://bullet.tscn" does not exist.). Bueno para activos fijos.
  • load() se resuelve en tiempo de ejecución y devuelve null con un error si la ruta es incorrecta. Úsalo para rutas construidas en tiempo de ejecución.
  • instantiate() (no el instance() de Godot 3) devuelve un Node; conviértelo al tipo que necesites. Libera las instancias con queue_free().

Encontrar nodos

extends Control

@onready var title: Label = %Title
@onready var start_button: Button = %StartButton
@onready var music: AudioStreamPlayer = $Music
@onready var optional_hint: Label = get_node_or_null("Hint")


func _ready() -> void:
	title.text = "Menú principal"
	start_button.grab_focus()
	if optional_hint:
		optional_hint.visible = false
	music.play()
  • $Path es get_node("Path"), relativo a este nodo. Da error si el nodo falta; usa get_node_or_null() para nodos opcionales.
  • %Name alcanza un nodo marcado como "Acceder como Nombre Único" (clic derecho en el dock de la Escena) en cualquier lugar de la misma escena, por lo que sobrevive a cambios de padre dentro de la escena. No alcanza escenas hijas instanciadas: usa $Child/%Name, o %Child/%Name cuando la instancia en sí es única.
  • Las variables @onready se asignan justo antes de _ready(). Son null en _init() y _enter_tree().
  • _ready() se ejecuta en los hijos antes que en su padre, por lo que el _ready() de un padre puede usar sus hijos, pero el _ready() de un hijo no debe depender de que el padre esté listo.
  • Tipifica las variables @onready (: Label) para que el analizador verifique los nombres de los miembros; $Label.txt en una ruta sin tipo solo se detecta en tiempo de ejecución.

Grupos

Los grupos etiquetan nodos a través de escenas. Agréguelos en el dock de Nodos (pestaña Grupos) o en código, luego consulta el árbol:

extends Node


func _ready() -> void:
	add_to_group("enemies")


func alert_all_enemies() -> void:
	get_tree().call_group("enemies", "set_alerted", true)
	for enemy in get_tree().get_nodes_in_group("enemies"):
		print(enemy.name)
	var player := get_tree().get_first_node_in_group("player") as Node2D
	if player:
		print("Jugador en ", player.global_position)

call_group() llama inmediatamente en Godot 4. Usa get_tree().call_group_flags(SceneTree.GROUP_CALL_DEFERRED, ...) para diferir.

Autoloads

Un autoload es un nodo creado antes de la escena principal y se mantiene a través de los cambios de escena. Úsalo para estado que sobrevive a una escena (configuraciones, datos guardados, un cambiador de escenas) y para un bus de eventos solo de señales. Regístralo en Proyecto > Ajustes del Proyecto > Globales > Autoload; project.godot entonces contiene:

[autoload]

Events="*res://autoload/events.gd"

El * significa que "Habilitado" está marcado, por lo que los scripts pueden usar el nombre directamente (Events.player_died.emit()). No hagas free() ni queue_free() a un autoload. Mantén pocos autoloads: cualquier cosa que pertenezca a un nivel debe vivir en la escena de ese nivel.

Nota para herramientas: godot --check-only --script no carga autoloads, por lo que un script que usa un nombre de autoload reporta Identifier not found: Events allí aunque funcione correctamente. Verifica dichos scripts ejecutando la escena (consulta el skill godot-verify).

class_name

class_name Player registra un tipo global, por lo que otros scripts pueden escribir var player: Player y obtener verificación de miembros. El editor mantiene un caché de clases global en .godot/; después de agregar un class_name fuera del editor, abre el editor o ejecuta godot --headless --path . --import antes de verificar los scripts que lo usan.

UIDs, archivos .uid y mover archivos

Godot 4 referencia recursos por UID además de por ruta. Las escenas y los recursos almacenan su propio UID en el encabezado del archivo, los activos importados en su archivo .import, y desde Godot 4.4 los scripts y shaders obtienen un archivo compañero (player.gd.uid, water.gdshader.uid). Una referencia guardada por el editor se ve así:

[ext_resource type="Script" uid="uid://dxxoiuob4eoum" path="res://game_manager.gd" id="1_feb5d"]

Reglas:

  • Incluye los archivos *.uid en el control de versiones. No los agregues a .gitignore.
  • Mueve y renombra archivos en el dock del Sistema de Archivos de Godot cuando puedas; actualiza las referencias.
  • Al mover un script o shader fuera de Godot (shell, IDE, agente), mueve su archivo .uid con él, luego abre el editor o ejecuta godot --headless --path . --import para que el caché de UID aprenda la nueva ruta. Hasta ese escaneo, se sigue usando la ruta anterior y la carga falla.
  • Si el archivo .uid se queda atrás, Godot genera un nuevo UID para el script movido y las escenas que referenciaban al antiguo recurren a su ruta obsoleta: WARNING: ... invalid UID: uid://... - using text path instead: res://old/path.gd, luego ERROR: ... referenced non-existent resource.
  • Al escribir un .tscn a mano, no inventes valores uid=. Omite el atributo y usa una path correcta; el editor agrega UIDs la próxima vez que guarde la escena.
  • Una escena de Godot 4 escrita a mano comienza con [gd_scene format=3] y referencia recursos por id de cadena: [ext_resource type="Script" path="res://main.gd" id="1_main"], luego script = ExtResource("1_main") en el nodo. Los nodos hijos necesitan parent="." o una ruta desde la raíz. Godot 4.7 también escribe unique_id= en los nodos; omítelo a mano.
  • load("uid://...") y preload("uid://...") aceptan cadenas UID. Copia un UID desde el menú contextual del dock del Sistema de Archivos; ResourceUID.id_to_text(ResourceLoader.get_resource_uid(path)) lo devuelve desde código.

Errores comunes

  • Acceder hacia arriba con get_parent().get_parent() o rutas absolutas como /root/Main/Player. Exporta una referencia, usa un grupo o emite una señal.
  • Usar un nodo en _init() o antes de que haya entrado en el árbol.
  • Codificar rutas res:// a escenas en muchos scripts en lugar de exportar un PackedScene.
  • Mover archivos .gd sin sus archivos .uid, o ignorar *.uid en git.
  • Hacer que todo sea un autoload porque es conveniente.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

ziva-sh/godot-4-api-pitfalls

Fixes Godot 3 APIs and GDScript syntax that AI assistants write into Godot 4 projects, such as KinematicBody2D, move_and_slide(velocity), export, onready, setget, yield, string connect(), instance(), rand_range, the Tween node, File, change_scene, Spatial, rect_* properties, Pool*Array, OS time functions and the old TileMap API. Use when writing, reviewing or porting GDScript for Godot 4.x, when a script fails with "not declared", "not found in base", "was removed in Godot 4" or "is not present

ziva-sh/godot-control-layout

Builds Godot 4 Control UIs that resize instead of clipping or overlapping - containers versus anchors, anchor presets from code, size flags, custom_minimum_size, MarginContainer margins, Label wrapping, mouse_filter, CanvasLayer HUDs, Godot 4 theme override names (add_theme_color_override and friends) and the display/window/stretch settings for multiple resolutions. Use when creating or fixing menus, HUDs, dialogs and inventory screens, when UI elements are cut off, zero-sized, overlapping, igno

ziva-sh/godot-signals

Godot 4 signal patterns and their failure modes - declaring typed signals, emit(), connect() and disconnect() with Callables, bind() and unbind(), lambdas, CONNECT_ONE_SHOT and CONNECT_DEFERRED, await on signals and timers, editor-made connections stored in .tscn files, and the call down, signal up rule. Use when wiring UI buttons, timers, Area2D or body events and custom game events, when replacing Godot 3 connect("signal", self, "method") or yield code, or when debugging "already connected", "

ziva-sh/godot-tilemaplayer

Correct Godot 4.3+ TileMapLayer code - set_cell(coords, source_id, atlas_coords), reading cells and custom data, erasing, coordinate conversion, terrains, tile collision through TileSet physics layers, finding the tile a body hit, and migrating from the deprecated TileMap node and its layer-index API. Use when placing, reading or erasing tiles from GDScript, building a TileSet in code, generating levels procedurally, handling tile collisions, or porting TileMap code from Godot 3 or Godot 4.0 to

Skills relacionados