Godot 4: Pon reglas de señales en tu prompt para que MCP conecte la barra de salud
Antes de pedir a Godot MCP en Cursor, define un contrato de señal health_changed para que el HUD se conecte sin rutas get_node profundas: plantillas de prompt, ejemplos GDScript, anti-patrones y aceptación en Play.
- Godot MCP
- Godot 4
- signals
- HUD
- GDScript
- Cursor
- AI game development
- tutorial
El problema: rutas de nodo frágiles
El fallo más común de “la IA rompió mi escena” en Godot no es un error de sintaxis—es un script de barra de salud que codifica rutas fijas:
$"/root/Game/Player/HitPoints".hp # o get_node("../../Player/...")
Reorganiza el árbol o instancia Player como escena hija, y esa ruta muere. Godot MCP sigue tu prompt fielmente—si no prohíbes rutas fijas, el modelo seguirá inventándolas.
Este post hace un solo trabajo: en Cursor (o Claude Code), establece primero un contrato de señal, luego deja que MCP conecte la salud del jugador a la barra del HUD. Sin guía de instalación, sin construcción completa de plataformas.
| Paso | Qué haces |
|---|---|
| 1 | Nombra la señal, argumentos, emisor / receptor |
| 2 | Prompt a MCP con restricciones para editar scripts y conexiones |
| 3 | Acepta en Play; corrige el prompt usando anti-patrones |
Relacionado:
Contexto: Organización de escenas — las escenas hijas deben exponer señales / exports, no rutas profundas.
Por qué las reglas de señales van en el prompt
| Enfoque | Corto plazo | Después de reorganizar |
|---|---|---|
get_node("../Player/Health") | Rápido | A menudo se rompe |
@onready var bar = %HealthBar (nombre único) | Bien en una escena | Aún frágil entre escenas |
signal health_changed(current, max) + connect | Dos líneas extra | Los árboles de HUD y Player pueden cambiar independientemente |
MCP no tiene “memoria de arquitectura” duradera a menos que repitas restricciones. Un bloque de contrato pegable es más barato que limpiar rutas fijas de cada diff.
Esqueleto mínimo de nodos
No necesitas una UI completa. v1 solo necesita:
Game (Node2D / Node)
├── Player (CharacterBody2D) ← player_health.gd
│ └── ...
└── HUD (CanvasLayer)
└── HealthBar (ProgressBar o TextureProgressBar) ← hud_health.gd
Nombres:
| Nodo | Nombre sugerido | Notas |
|---|---|---|
| Raíz de Player | Player | Posee el script de salud |
| Capa HUD | HUD | CanvasLayer |
| Barra | HealthBar | ProgressBar; HP absoluto o max_value = 1 ratio |
Si el HUD proviene de AI Studio, renombra a IDs estables en inglés antes de cablear.
Contrato de señal (pegar al inicio de cada prompt)
Trátalo como ley del proyecto:
[Contrato de señal — salud]
1. Solo el script de salud en Player emite:
signal health_changed(current: float, max_health: float)
Nombrado en pasado / completado; argumentos siempre (current, max_health).
2. El script de la barra del HUD solo conecta esa señal y actualiza ProgressBar; sin get_node a Player desde HUD.
3. Prohibido: NodePaths profundos entre escenas, Autoload como bus de salud (no necesario aquí), sondeo de Player en _process.
4. Prefiere conexiones de señal del editor, o @export Node / NodePath en el HUD y luego .connect — nunca codificar "/root/...".
5. Daño y curación solo cambian valores en Player y emiten; la UI nunca muta HP.
Ese bloque es el punto de este artículo: contrato antes de implementación.
Paso 1: Prueba de humo de solo lectura
Lista los nombres de los hijos bajo la raíz de la escena actualmente editada. No modifiques archivos ni nodos.
Solo escribe una vez que veas Player y HUD (o tus equivalentes).
Paso 2: Player solo emite
Añade después del contrato:
[Contrato de señal — salud] (pega el bloque completo)
En res://scripts/player_health.gd (crear si falta) y adjuntar a Player:
- @export var max_health: float = 100.0
- var current: float
- signal health_changed(current: float, max_health: float)
- En _ready: current = max_health; emitir health_changed una vez
- take_damage(amount), heal(amount); clamp 0..max_health; emitir después de cada cambio
- No referenciar HUD; no get_node a UI
Guardar y reportar tipos de argumentos de la señal.
Implementación de referencia:
extends Node
class_name PlayerHealth
signal health_changed(current: float, max_health: float)
@export var max_health: float = 100.0
var current: float
func _ready() -> void:
current = max_health
health_changed.emit(current, max_health)
func take_damage(amount: float) -> void:
if amount <= 0.0 or current <= 0.0:
return
current = maxf(0.0, current - amount)
health_changed.emit(current, max_health)
func heal(amount: float) -> void:
if amount <= 0.0 or current <= 0.0:
return
current = minf(max_health, current + amount)
health_changed.emit(current, max_health)
Tecla de daño temporal (eliminar después):
Añade debug_damage.gd temporal en Player: presionar H llama a PlayerHealth.take_damage(10) en el mismo nodo (o padre). Solo para aceptación de cableado. No tocar HUD.
Si el script está en la raíz de Player, cambia extends Node para que coincida (ej. CharacterBody2D), o haz PlayerHealth un hijo Health—elige uno en el prompt para que MCP no adivine el punto de montaje.
Paso 3: HUD se suscribe mediante referencia exportada
[Contrato de señal — salud] (pega el bloque completo)
Crear res://scripts/hud_health.gd en HUD o HealthBar:
- @export var player_health: PlayerHealth
- @onready var bar: ProgressBar = $HealthBar # solo si el script está en HUD; la ruta permanece dentro del subárbol HUD
- _ready: assert player_health != null; player_health.health_changed.connect(_on_health_changed)
- _on_health_changed(current, max_health): bar.max_value = max_health; bar.value = current
(o ratio: max_value = 1; value = current / max_health)
- Prohibido: get_node a Player; prohibido: rutas absolutas /root
Luego asigna el player_health exportado al PlayerHealth de Player (o hijo Health) en el editor. Guarda la escena.
Referencia:
extends CanvasLayer
@export var player_health: PlayerHealth
@onready var bar: ProgressBar = $HealthBar
func _ready() -> void:
assert(player_health != null, "Asigna PlayerHealth en el inspector")
player_health.health_changed.connect(_on_health_changed)
func _on_health_changed(current: float, max_health: float) -> void:
bar.max_value = max_health
bar.value = current
$HealthBar dentro del HUD está bien—mismo subárbol. Prohibido es una ruta profunda hacia Player.
La conexión del editor “Nodo → Conectar una señal” vía MCP también está bien:
Conecta vía editor: Player (PlayerHealth) health_changed → script HUD _on_health_changed. No escribas cadenas NodePath a mano.
Paso 4: Lista de aceptación en Play
- Al entrar: barra llena (o ratio correcto)
- Presiona H:
bar.valuebaja - A 0: barra vacía; la UI no debe escribir
current - Después de
heal: barra sube - Reorganiza
Playerbajo ej.Entitiesy juega de nuevo: la barra aún se actualiza si la ref exportada permanece—esa es la victoria vs rutas fijas
Si se rompe después de reorganizar, arregla el export vacío—no pidas a MCP “otro get_node”.
Prompt de aceptación:
Diagnostica desde errores de Play: si la señal nunca se dispara, revisa connect; si player_health es null, solo arregla el export. No "arregles" con rutas get_node absolutas. Diagnostica primero; espera mi OK antes de editar.
Anti-patrones: cambia el prompt, no fusiones
| Anti-patrón | Por qué duele | Añade al prompt |
|---|---|---|
get_node("/root/Game/Player") | Cambio de ruta raíz | ”No /root o NodePath absoluto” |
get_parent().get_node("Player") | Acoplamiento de hermanos | ”HUD no debe asumir disposición de hermanos de Player” |
Autoload GlobalHealth.hp | Cajón global de basura | ”No nuevo Autoload para esta tarea” |
HUD _process buscando Player | Lento y frágil | ”No sondeo; solo señales” |
Señal llamada update / set_hp | Vaga, propensa a colisiones | ”La señal debe ser health_changed” |
Escribir a mano aún gana para movimiento de ruta crítica y matemática de combate compleja; el cableado de barra de salud es boilerplate donde un prompt MCP contratado suele ser más barato. Ver Godot MCP vs scripting manual.
Esqueleto reutilizable “contrato + tarea”
Intercambia nombres para maná / barras de jefe:
[Contrato de señal]
- Emisor: <nodo/script>
- signal <nombre>(...)
- Receptor: <método HUD>
- Prohibido: NodePath absoluto, bus Autoload, sondeo _process
[Tarea]
1. …
2. …
3. Guarda la escena; lista nuevas señales y cómo se conectan (editor / .connect)
Resumen
- Las rutas fijas son un agujero en el prompt, no “MCP no puede Godot”
- Pega
health_changed(current, max_health)antes de pedir ediciones - Player solo emite; HUD solo conecta y actualiza
ProgressBar - Los enlaces entre objetos usan
@exporto conexión de señal del editor—no/root/... - Acepta reorganizando Player y viendo la barra—no por “script generado OK”
Ahora tienes un conjunto de reglas de prompt Godot MCP pegable; inventario, registro de misiones y contadores de muertes pueden reutilizar el mismo patrón.
Seguir leyendo
Más guías que te pueden interesar
Diseño de UI para juegos: flujo de trabajo tradicional vs arte con IA + división en VberAI Studio
Compara el corte manual de UI en PS/Figma con VberAI Studio: importa o genera UI con IA, divide capas automáticamente y exporta PSD por capas o sets de imágenes.
- game-ui-design
- game-ui-designer-flow
- ui-slicing
- AIGC
Cómo activar el plugin MCP en Godot: de la descarga a las herramientas en Cursor
Activa el Godot MCP de código abierto en Godot: descarga el plugin, ponlo en addons, actívalo en Ajustes del proyecto, inicia el servidor local y confirma godot-mcp en Cursor u otros IDE con MCP.
- godot
- mcp
- cursor
- tutorial
Jerarquía de información del HUD móvil: qué mostrar en combate, lobby y modales
Visibilidad y prioridad del HUD según el estado de juego; su relación con Safe Area, capas de texto flotante y apilado de modales, con tablas y pasos de aceptación en dispositivo.
- game-ui-design
- game-dev-ai
- ui-to-engine
- hud