GDScript en el día a día: cómo se conecta con tus nodos
GDScript es el lenguaje que usarás para darle comportamiento a los nodos de tu escena. En la práctica, casi todo se resume a: leer datos (variables), reaccionar a eventos (señales e input) y actualizar el estado del juego en el tiempo (funciones de ciclo de vida como _ready(), _process() y _physics_process()).
Crear y adjuntar un script (recordatorio práctico)
- Selecciona un nodo en tu escena (por ejemplo,
Node2DoCharacterBody2D). - Haz clic en “Attach Script”.
- Abre el script y prueba los ejemplos de este capítulo.
Variables y tipos: datos que controlan tu lógica
Una variable guarda un valor que tu juego usa para decidir qué hacer: velocidad, vida, puntuación, etc. En Godot 4, es buena práctica tipar variables para detectar errores antes.
Variables sin tipo vs variables tipadas
extends Node2D
var sin_tipo = 10
var velocidad: float = 250.0
var nombre: String = "Player"
var vivo: bool = true
Tipos comunes en 2D:
int,float,bool,StringVector2(posiciones, direcciones, velocidades)Color,Rect2- Referencias a nodos:
Sprite2D,Label,CharacterBody2D, etc.
Ejemplo verificable: imprimir variables en la consola
Pega esto en un script de cualquier nodo y ejecuta la escena:
extends Node
var puntos: int = 0
var posicion_inicial: Vector2 = Vector2(100, 50)
func _ready() -> void:
print("Puntos:", puntos)
print("Posición inicial:", posicion_inicial)
puntos += 10
print("Puntos tras sumar:", puntos)
Verás las salidas en la pestaña “Output”.
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
Funciones: encapsular comportamiento
Una función agrupa instrucciones con un propósito claro. Puedes recibir parámetros y devolver valores.
Ejemplo: función que calcula daño
extends Node
func calcular_danio(base: int, critico: bool) -> int:
if critico:
return base * 2
return base
func _ready() -> void:
print(calcular_danio(10, false)) # 10
print(calcular_danio(10, true)) # 20
Buenas prácticas rápidas
- Nombra funciones con verbos:
mover(),disparar(),recibir_danio(). - Tipa parámetros y retorno cuando puedas.
- Evita funciones gigantes: divide en partes.
Ciclo de vida: _ready(), _process() y _physics_process()
Estas funciones se llaman automáticamente en momentos específicos. Entenderlas evita bugs típicos (por ejemplo, mover física en _process o leer nodos antes de que existan).
| Función | Cuándo se ejecuta | Uso típico |
|---|---|---|
_ready() | Una vez, cuando el nodo y sus hijos están listos | Inicializar, obtener referencias, conectar señales |
_process(delta) | Cada frame (variable) | Animaciones por frame, UI, timers simples |
_physics_process(delta) | En pasos fijos de física | Movimiento con colisiones, gravedad, move_and_slide() |
Ejemplo verificable: contador de tiempo y movimiento simple
Adjunta este script a un Node2D y ejecuta. Verás impresiones y el nodo se moverá en X:
extends Node2D
var tiempo: float = 0.0
func _ready() -> void:
print("Listo. Posición inicial:", position)
func _process(delta: float) -> void:
tiempo += delta
if int(tiempo) % 1 == 0:
# Ojo: esto se cumple muchas veces; es solo demostración
pass
func _physics_process(delta: float) -> void:
position.x += 60.0 * delta
Nota práctica: si quieres imprimir “cada 1 segundo” de verdad, usa un acumulador y compara con un umbral (lo verás más abajo en el laboratorio).
Input: leer teclas y acciones
En Godot, lo más cómodo es usar acciones del InputMap (por ejemplo: ui_left, ui_right, ui_accept). Así tu juego no depende de una tecla específica.
Ejemplo verificable: detectar pulsación
extends Node
func _process(delta: float) -> void:
if Input.is_action_just_pressed("ui_accept"):
print("Aceptar presionado")
Ejemplo verificable: eje horizontal con get_axis
extends Node
func _process(delta: float) -> void:
var x := Input.get_axis("ui_left", "ui_right")
if x != 0:
print("Eje horizontal:", x)
Acceso al árbol de nodos: obtener y modificar otros nodos
Tu script vive en un nodo, pero normalmente necesita hablar con otros: un Sprite2D para cambiar su color, un Label para mostrar vida, etc. Para eso se usa el árbol de nodos.
Rutas y get_node()
Si tu escena tiene una estructura como:
Player (Node2D)
├─ Sprite2D
└─ Label
Desde el script en Player puedes hacer:
extends Node2D
func _ready() -> void:
var sprite := get_node("Sprite2D") as Sprite2D
var label := get_node("Label") as Label
label.text = "Hola"
sprite.modulate = Color(1, 0.8, 0.8)
Atajo recomendado: @onready
@onready evalúa la referencia cuando el nodo ya está listo (evita nulos por orden de carga).
extends Node2D
@onready var label: Label = $Label
@onready var sprite: Sprite2D = $Sprite2D
func _ready() -> void:
label.text = "Listo"
sprite.rotation = 0.2
Señales: eventos que conectan nodos sin acoplarlos
Una señal es un evento. Por ejemplo: un botón emite pressed, un área emite body_entered. Puedes conectar señales desde el editor o por código.
Conectar una señal por código (ejemplo verificable)
Crea un nodo Button (en una escena UI) y adjunta este script al nodo padre (por ejemplo, Control). Asegúrate de que el botón se llame Button.
extends Control
@onready var button: Button = $Button
func _ready() -> void:
button.pressed.connect(_on_button_pressed)
func _on_button_pressed() -> void:
print("Botón presionado")
Al ejecutar y hacer clic, verás el mensaje en consola.
Crear tus propias señales
También puedes definir señales en tus scripts para avisar a otros sistemas (por ejemplo, “murió el jugador” o “cambió la vida”).
extends Node
signal vida_cambiada(nueva_vida: int)
var vida: int = 100
func recibir_danio(cantidad: int) -> void:
vida = max(vida - cantidad, 0)
vida_cambiada.emit(vida)
@export: parámetros configurables desde el Inspector
@export expone variables en el Inspector para ajustar valores sin tocar código. Esto acelera el ajuste fino (tuning) de velocidad, gravedad, saltos, etc.
Ejemplo: exportar velocidad y color
extends Node2D
@export var velocidad: float = 200.0
@export var color: Color = Color(1, 1, 1)
@onready var sprite: Sprite2D = $Sprite2D
func _ready() -> void:
sprite.modulate = color
print("Velocidad configurada:", velocidad)
Ejecuta la escena, cambia velocidad y color desde el Inspector y vuelve a ejecutar para validar.
Export con rangos (útil para tuning)
@export_range(0.0, 1000.0, 10.0) var velocidad: float = 250.0
Mini-laboratorio: script de Jugador configurable y validación en ejecución
Objetivo: crear un Jugador con movimiento horizontal, gravedad y salto, donde velocidad y gravedad se ajusten desde el Inspector. Validarás que los cambios afectan el comportamiento al ejecutar.
Paso 1: Preparar el nodo Jugador
- Crea un nodo
CharacterBody2DllamadoJugador. - Como hijos, agrega:
CollisionShape2D(con una forma) y opcionalmenteSprite2Dpara verlo. - Adjunta un script nuevo a
Jugador.
Paso 2: Escribir el script con @export y lógica de movimiento
Pega este código en el script de Jugador:
extends CharacterBody2D
@export_range(0.0, 800.0, 10.0) var velocidad: float = 220.0
@export_range(0.0, 3000.0, 50.0) var gravedad: float = 1200.0
@export_range(0.0, 1200.0, 10.0) var fuerza_salto: float = 420.0
var _acum_log: float = 0.0
func _ready() -> void:
print("Jugador listo")
print("velocidad=", velocidad, " gravedad=", gravedad, " salto=", fuerza_salto)
func _physics_process(delta: float) -> void:
# 1) Gravedad
if not is_on_floor():
velocity.y += gravedad * delta
else:
# Evita acumular velocidad hacia abajo al tocar el piso
if velocity.y > 0:
velocity.y = 0
# 2) Movimiento horizontal
var dir_x := Input.get_axis("ui_left", "ui_right")
velocity.x = dir_x * velocidad
# 3) Salto
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = -fuerza_salto
# 4) Aplicar movimiento con colisiones
move_and_slide()
# 5) Validación simple en consola (cada 0.5s)
_acum_log += delta
if _acum_log >= 0.5:
_acum_log = 0.0
print("pos=", global_position, " vel=", velocity)
Paso 3: Validar en ejecución (pruebas rápidas)
- Ejecuta la escena y mueve con
ui_left/ui_right(flechas o A/D según tu InputMap). - Salta con
ui_accept(por defecto Enter/Espacio según configuración). - Observa en consola el log de posición y velocidad cada 0.5s.
Paso 4: Ajuste desde el Inspector (comprobación de que @export funciona)
- Con el nodo
Jugadorseleccionado, cambiavelocidad(por ejemplo, 220 → 400) y ejecuta: deberías moverte más rápido. - Cambia
gravedad(1200 → 2000) y ejecuta: caerás más rápido y el salto se sentirá más “pesado”. - Cambia
fuerza_salto(420 → 600) y ejecuta: el salto alcanzará mayor altura.
Paso 5 (opcional): cambiar una propiedad visual al moverte
Si tu Jugador tiene un Sprite2D hijo, añade esto para verificar acceso al árbol de nodos y cambios de propiedades:
@onready var sprite: Sprite2D = $Sprite2D
func _physics_process(delta: float) -> void:
# ... tu código anterior ...
if velocity.x != 0:
sprite.modulate = Color(0.8, 1.0, 0.8)
else:
sprite.modulate = Color(1.0, 1.0, 1.0)