Godot 4 : Mettez les règles de signaux dans votre invite pour que MCP câble la barre de vie
Avant de demander à Godot MCP dans Cursor, définissez un contrat de signal health_changed pour que le HUD se connecte sans chemins get_node profonds—modèles d'invite, exemples GDScript, anti-patterns et acceptation dans Play.
- Godot MCP
- Godot 4
- signals
- HUD
- GDScript
- Cursor
- AI game development
- tutorial
L’échec « l’IA a cassé ma scène » le plus courant dans Godot n’est pas une erreur de syntaxe—c’est un script de barre de vie qui code en dur :
$"/root/Game/Player/HitPoints".hp # ou get_node("../../Player/...")
Réorganisez l’arbre ou instanciez Player comme scène enfant, et ce chemin meurt. Godot MCP suit votre invite fidèlement—si vous n’interdisez pas les chemins durs, le modèle continuera d’en inventer.
Ce post fait une seule chose : dans Cursor (ou Claude Code), énoncez d’abord un contrat de signal, puis laissez MCP câbler la santé du joueur à la barre HUD. Pas de tutoriel d’installation, pas de construction complète de plateforme.
| Étape | Ce que vous faites |
|---|---|
| 1 | Nommez le signal, les arguments, l’émetteur / le récepteur |
| 2 | Invitez MCP avec des contraintes pour modifier les scripts et les connexions |
| 3 | Acceptez dans Play ; corrigez l’invite en utilisant les anti-patterns |
Liens connexes :
Contexte : Organisation des scènes — les scènes enfants doivent exposer des signaux / exports, pas des chemins profonds.
Pourquoi les règles de signaux appartiennent à l’invite
| Approche | Court terme | Après réorganisation |
|---|---|---|
get_node("../Player/Health") | Rapide | Se casse souvent |
@onready var bar = %HealthBar (nom unique) | Bien dans une scène | Toujours fragile entre scènes |
signal health_changed(current, max) + connect | Deux lignes supplémentaires | Les arbres HUD et Player peuvent changer indépendamment |
MCP n’a pas de « mémoire d’architecture » durable à moins que vous ne répétiez les contraintes. Un bloc de contrat copiable est moins cher que de nettoyer les chemins durs dans chaque diff.
Squelette de nœuds minimal
Vous n’avez pas besoin d’une UI complète. La v1 n’a besoin que de :
Game (Node2D / Node)
├── Player (CharacterBody2D) ← player_health.gd
│ └── ...
└── HUD (CanvasLayer)
└── HealthBar (ProgressBar ou TextureProgressBar) ← hud_health.gd
Nommage :
| Nœud | Nom suggéré | Notes |
|---|---|---|
| Racine Player | Player | Possède le script de santé |
| Couche HUD | HUD | CanvasLayer |
| Barre | HealthBar | ProgressBar ; HP absolu ou max_value = 1 ratio |
Si le HUD provient de AI Studio, renommez-le en identifiants anglais stables avant le câblage.
Contrat de signal (à coller en haut de chaque invite)
Traitez cela comme une loi de projet :
[Contrat de signal — santé]
1. Seul le script de santé sur Player émet :
signal health_changed(current: float, max_health: float)
Nommage au passé / complété ; arguments toujours (current, max_health).
2. Le script de la barre HUD ne fait que connecter ce signal et mettre à jour ProgressBar ; pas de get_node vers Player depuis HUD.
3. Interdit : NodePaths profonds entre scènes, Autoload comme bus de santé (pas nécessaire ici), polling de Player dans _process.
4. Préférez les connexions de signaux dans l'éditeur, ou @export Node / NodePath sur le HUD puis .connect — ne codez jamais en dur "/root/...".
5. Les dégâts et les soins ne modifient que les valeurs sur Player et émettent ; l'UI ne mute jamais les HP.
Ce bloc est le but de cet article : contrat avant implémentation.
Étape 1 : Test de fumée en lecture seule
Listez les noms des enfants sous la racine de la scène actuellement éditée. Ne modifiez aucun fichier ni nœud.
N’écrivez qu’une fois que vous voyez Player et HUD (ou vos équivalents).
Étape 2 : Player émet uniquement
Ajoutez après le contrat :
[Contrat de signal — santé] (collez le bloc complet)
Dans res://scripts/player_health.gd (créez-le s'il manque) et attachez-le à Player :
- @export var max_health: float = 100.0
- var current: float
- signal health_changed(current: float, max_health: float)
- Dans _ready : current = max_health ; émettez health_changed une fois
- take_damage(amount), heal(amount) ; clampez 0..max_health ; émettez après chaque changement
- Ne référencez pas HUD ; ne faites pas de get_node dans l'UI
Enregistrez et rapportez les types d'arguments du signal.
Implémentation de référence :
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)
Touche de dégâts temporaire (à supprimer plus tard) :
Ajoutez un debug_damage.gd temporaire sur Player : appuyer sur H appelle PlayerHealth.take_damage(10) sur le même nœud (ou parent). Uniquement pour l'acceptation du câblage. Ne touchez pas au HUD.
Si le script se trouve sur la racine Player, changez extends Node pour correspondre (par exemple CharacterBody2D), ou faites de PlayerHealth un enfant Health—choisissez-en un dans l’invite pour que MCP ne devine pas le point de montage.
Étape 3 : Le HUD s’abonne via une référence exportée
[Contrat de signal — santé] (collez le bloc complet)
Créez res://scripts/hud_health.gd sur HUD ou HealthBar :
- @export var player_health: PlayerHealth
- @onready var bar: ProgressBar = $HealthBar # uniquement si le script est sur HUD ; le chemin reste dans le sous-arbre 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
(ou ratio : max_value = 1 ; value = current / max_health)
- Interdit : get_node vers Player ; interdit : chemins absolus /root
Ensuite, assignez le player_health exporté au PlayerHealth de Player (ou à l'enfant Health) dans l'éditeur. Enregistrez la scène.
Référence :
extends CanvasLayer
@export var player_health: PlayerHealth
@onready var bar: ProgressBar = $HealthBar
func _ready() -> void:
assert(player_health != null, "Assignez PlayerHealth dans l'inspecteur")
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 à l’intérieur du HUD est acceptable—même sous-arbre. Interdit est un chemin profond vers Player.
La connexion via l’éditeur « Nœud → Connecter un signal » via MCP est également acceptable :
Connectez via l'éditeur : Player (PlayerHealth) health_changed → script HUD _on_health_changed. N'écrivez pas de chaînes NodePath à la main.
Étape 4 : Liste de contrôle d’acceptation dans Play
- À l’entrée : barre pleine (ou ratio correct)
- Appuyez sur H :
bar.valuediminue - À 0 : barre vide ; l’UI ne doit pas écrire
current - Après
heal: la barre monte - Re-parentez
Playersous par exempleEntitieset rejouez : la barre se met toujours à jour si la référence exportée reste—c’est la victoire par rapport aux chemins durs
Si cela casse après le re-parentage, corrigez l’export vide—ne demandez pas à MCP un « autre get_node ».
Invite d’acceptation :
Diagnostiquez à partir des erreurs de Play : si le signal ne se déclenche jamais, vérifiez la connexion ; si player_health est null, corrigez uniquement l'export. Ne « corrigez » pas avec des chemins get_node absolus. Diagnostiquez d'abord ; attendez mon OK avant de modifier.
Anti-patterns : changez l’invite, ne fusionnez pas
| Anti-pattern | Pourquoi c’est nuisible | Ajoutez à l’invite |
|---|---|---|
get_node("/root/Game/Player") | Instabilité du chemin racine | « Pas de /root ni de NodePath absolu » |
get_parent().get_node("Player") | Couplage entre frères | « Le HUD ne doit pas supposer la disposition des frères de Player » |
Autoload GlobalHealth.hp | Tiroir global | « Pas de nouvel Autoload pour cette tâche » |
HUD _process cherchant Player | Lent et fragile | « Pas de polling ; signaux uniquement » |
Signal nommé update / set_hp | Vague, sujet aux collisions | « Le signal doit être health_changed » |
L’écriture manuelle reste gagnante pour les mouvements à chemin chaud et les maths de combat complexes ; le câblage de barre de vie est du boilerplate où une invite MCP contractée est généralement moins chère. Voir Godot MCP vs script manuel.
Squelette réutilisable « contrat + tâche »
Échangez les noms pour la mana / les barres de boss :
[Contrat de signal]
- Émetteur : <nœud/script>
- signal <nom>(...)
- Récepteur : <méthode HUD>
- Interdit : NodePath absolu, bus Autoload, polling _process
[Tâche]
1. …
2. …
3. Enregistrez la scène ; listez les nouveaux signaux et comment ils se connectent (éditeur / .connect)
Résumé
- Les chemins durs sont un trou d’invite, pas « MCP ne sait pas faire Godot »
- Collez
health_changed(current, max_health)avant de demander des modifications - Player émet uniquement ; HUD connecte et met à jour
ProgressBaruniquement - Les liens entre objets utilisent
@exportou la connexion de signal de l’éditeur—pas/root/... - Acceptez en re-parentant Player et en regardant la barre—pas par « script généré OK »
Vous avez maintenant un ensemble de règles d’invite Godot MCP copiable ; inventaire, journal de quêtes et compteurs de kills peuvent réutiliser le même modèle.
Poursuivre la lecture
D’autres guides qui pourraient vous intéresser
Suppression d'arrière-plan gratuite dans VberAI : découpes Glow / VFX / semi-transparentes avec PNG + Alpha
VberAI AI Super Matting : détourage gratuit pour FX glow, suppression d'arrière-plan IA jusqu'à 4096×4096, et Super IA pour cheveux et bords semi-transparents avec PNG Alpha.
- vberai
- ai-super-matting
- matting
- super-matting
VberAI de bout en bout : AI Studio + Engine MCP pour un mini-jeu jouable
Générez ou importez l'UI dans AI Studio, puis pilotez la logique et le débogage via Cursor avec Godot, Unity ou Cocos MCP. Démo chibi match-3 incluse.
- VberAI
- AI Studio
- Unity MCP
- Godot MCP
Nombres de dégâts flottants : acceptation de la passation et implémentation moteur
Critères d'échec : popups flous, glyphes manquants, tri erroné ou saccades ; TMP vs chiffres bitmap, pools et ordre Canvas, étapes d'acceptation Unity UGUI.
- game-ui-design
- game-dev-ai
- ui-to-engine
- bitmap-font