Godot 4: Signal-Regeln im Prompt definieren, damit MCP die Health Bar verdrahtet
Bevor Sie Godot MCP in Cursor ansprechen, definieren Sie einen health_changed-Signalvertrag, damit das HUD ohne tiefe get_node-Pfade verbunden wird — Prompt-Vorlagen, GDScript-Beispiele, Anti-Patterns und Play-Akzeptanz.
- Godot MCP
- Godot 4
- signals
- HUD
- GDScript
- Cursor
- AI game development
- tutorial
Der häufigste „KI hat meine Szene kaputt gemacht“-Fehler in Godot ist kein Syntaxfehler — es ist ein Health-Bar-Skript, das hart codiert:
$"/root/Game/Player/HitPoints".hp # or get_node("../../Player/...")
Verschieben Sie den Baum oder instanziieren Sie Player als Kind-Szene, und dieser Pfad ist tot. Godot MCP folgt Ihrem Prompt zuverlässig — wenn Sie harte Pfade nicht verbieten, erfindet das Modell sie weiter.
Dieser Beitrag hat eine Aufgabe: In Cursor (oder Claude Code) zuerst einen Signalvertrag festlegen, dann MCP Player-Health mit der HUD-Bar verdrahten lassen. Keine Installationsanleitung, kein vollständiger Platformer-Build.
| Schritt | Was Sie tun |
|---|---|
| 1 | Signal, Argumente, Emitter / Empfänger benennen |
| 2 | MCP mit Constraints zum Bearbeiten von Skripten und Verbindungen prompten |
| 3 | In Play akzeptieren; Prompt anhand von Anti-Patterns korrigieren |
Verwandt:
Hintergrund: Scene organization — Kind-Szenen sollten Signale / Exports bereitstellen, keine tiefen Pfade.
Warum Signal-Regeln in den Prompt gehören
| Ansatz | Kurzfristig | Nach Reorganisation |
|---|---|---|
get_node("../Player/Health") | Schnell | Bricht oft |
@onready var bar = %HealthBar (Unique Name) | In einer Szene ok | Über Szenen hinweg weiterhin brüchig |
signal health_changed(current, max) + connect | Zwei zusätzliche Zeilen | HUD- und Player-Bäume können unabhängig geändert werden |
MCP hat kein dauerhaftes „Architektur-Gedächtnis“, es sei denn, Sie wiederholen Constraints. Ein einfügbarer Vertragsblock ist günstiger, als harte Pfade aus jedem Diff zu entfernen.
Minimales Knoten-Skelett
Sie brauchen keine vollständige UI. v1 benötigt nur:
Game (Node2D / Node)
├── Player (CharacterBody2D) ← player_health.gd
│ └── ...
└── HUD (CanvasLayer)
└── HealthBar (ProgressBar or TextureProgressBar) ← hud_health.gd
Benennung:
| Knoten | Empfohlener Name | Hinweise |
|---|---|---|
| Player-Root | Player | Besitzt Health-Skript |
| HUD-Layer | HUD | CanvasLayer |
| Bar | HealthBar | ProgressBar; absolute HP oder max_value = 1 als Verhältnis |
Wenn das HUD aus AI Studio stammt, benennen Sie es vor dem Verdrahten in stabile englische IDs um.
Signalvertrag (oben in jeden Prompt einfügen)
Behandeln Sie dies als Projektgesetz:
[Signalvertrag — Health]
1. Nur das Health-Skript auf Player emittiert:
signal health_changed(current: float, max_health: float)
Vergangenheits-/abgeschlossene Benennung; Argumente immer (current, max_health).
2. HUD-Bar-Skript verbindet nur dieses Signal und aktualisiert ProgressBar; kein get_node zu Player vom HUD aus.
3. Verboten: tiefe Cross-Scene-NodePaths, Autoload als Health-Bus (hier nicht nötig), Polling nach Player in _process.
4. Bevorzugt: Editor-Signalverbindungen oder @export Node / NodePath am HUD, dann .connect — niemals "/root/..." hart codieren.
5. Schaden und Heilung ändern nur Werte auf Player und emittieren; UI mutiert niemals HP.
Dieser Block ist der Kern des Artikels: Vertrag vor Implementierung.
Schritt 1: Read-only Smoke Test
Listen Sie die Kindnamen unter dem Root der aktuell bearbeiteten Szene auf. Ändern Sie keine Dateien oder Knoten.
Schreiben Sie erst, wenn Sie Player und HUD (oder Ihre Äquivalente) sehen.
Schritt 2: Player emittiert nur
Nach dem Vertrag anhängen:
[Signalvertrag — Health] (vollständigen Block einfügen)
In res://scripts/player_health.gd (bei Bedarf erstellen) und an Player anhängen:
- @export var max_health: float = 100.0
- var current: float
- signal health_changed(current: float, max_health: float)
- In _ready: current = max_health; health_changed einmal emittieren
- take_damage(amount), heal(amount); clamp 0..max_health; nach jeder Änderung emittieren
- Kein Verweis auf HUD; kein get_node in die UI
Speichern und Signal-Argumenttypen melden.
Referenzimplementierung:
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)
Temporäre Schaden-Taste (später löschen):
Fügen Sie temporär debug_damage.gd auf Player hinzu: Drücken von H ruft PlayerHealth.take_damage(10) auf demselben Knoten (oder Parent) auf. Nur für Verdrahtungs-Akzeptanz. HUD nicht anfassen.
Wenn das Skript auf dem Player-Root sitzt, ändern Sie extends Node entsprechend (z. B. CharacterBody2D), oder machen Sie PlayerHealth zu einem Kind Health — legen Sie einen Mount-Punkt im Prompt fest, damit MCP nicht raten muss.
Schritt 3: HUD abonniert über exportierte Referenz
[Signalvertrag — Health] (vollständigen Block einfügen)
Erstellen Sie res://scripts/hud_health.gd auf HUD oder HealthBar:
- @export var player_health: PlayerHealth
- @onready var bar: ProgressBar = $HealthBar # nur wenn Skript auf HUD; Pfad bleibt innerhalb des HUD-Subtrees
- _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
(oder Verhältnis: max_value = 1; value = current / max_health)
- Verboten: get_node zu Player; verboten: /root absolute Pfade
Weisen Sie dann player_health im Editor dem PlayerHealth (oder Health-Kind) von Player zu. Szene speichern.
Referenz:
extends CanvasLayer
@export var player_health: PlayerHealth
@onready var bar: ProgressBar = $HealthBar
func _ready() -> void:
assert(player_health != null, "Assign PlayerHealth in the 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 innerhalb des HUD ist in Ordnung — gleicher Subtree. Verboten ist ein tiefer Pfad über zu Player.
Editor „Node → Connect a Signal“ über MCP ist ebenfalls ok:
Über den Editor verbinden: Player (PlayerHealth) health_changed → HUD-Skript _on_health_changed. Keine NodePath-Strings von Hand schreiben.
Schritt 4: Play-Akzeptanz-Checkliste
- Beim Start: Bar voll (oder korrektes Verhältnis)
- H drücken:
bar.valuesinkt - Bei 0: Bar leer; UI darf
currentnicht schreiben - Nach
heal: Bar steigt Playerz. B. unterEntitiesreparenten und erneut Play: Bar aktualisiert sich weiter, wenn die Export-Referenz bestehen bleibt — das ist der Gewinn gegenüber harten Pfaden
Bricht es nach Reparenting, leere Export-Referenz korrigieren — MCP nicht nach „noch einem get_node“ fragen.
Akzeptanz-Prompt:
Aus Play-Fehlern diagnostizieren: wenn das Signal nie feuert, connect prüfen; wenn player_health null ist, nur Export korrigieren. Nicht mit absoluten get_node-Pfaden „reparieren“. Zuerst diagnostizieren; auf mein OK warten, bevor Sie bearbeiten.
Anti-Patterns: Prompt ändern, nicht mergen
| Anti-Pattern | Warum es schadet | Zum Prompt hinzufügen |
|---|---|---|
get_node("/root/Game/Player") | Root-Pfad-Wechsel | „Kein /root oder absoluter NodePath“ |
get_parent().get_node("Player") | Geschwister-Kopplung | „HUD darf Player-Geschwister-Layout nicht voraussetzen“ |
Autoload GlobalHealth.hp | Globaler Sammelordner | „Kein neuer Autoload für diese Aufgabe“ |
HUD _process sucht Player | Langsam und brüchig | „Kein Polling; nur Signale“ |
Signal heißt update / set_hp | Vage, kollisionsanfällig | „Signal muss health_changed heißen“ |
Handschreiben gewinnt weiterhin bei Hot-Path-Bewegung und komplexer Kampf-Mathematik; Health-Bar-Verdrahtung ist Boilerplate, wo ein vertraglich definierter MCP-Prompt meist günstiger ist. Siehe Godot MCP vs. manuelles Skripting.
Wiederverwendbares „Vertrag + Aufgabe“-Skelett
Namen für Mana / Boss-Bars tauschen:
[Signalvertrag]
- Emitter: <Knoten/Skript>
- signal <name>(...)
- Empfänger: <HUD-Methode>
- Verboten: absoluter NodePath, Autoload-Bus, _process-Polling
[Aufgabe]
1. …
2. …
3. Szene speichern; neue Signale und Verbindungen auflisten (Editor / .connect)
Zusammenfassung
- Harte Pfade sind ein Prompt-Loch, nicht „MCP kann kein Godot“
health_changed(current, max_health)einfügen, bevor Sie nach Bearbeitungen fragen- Player emittiert nur; HUD verbindet nur und aktualisiert
ProgressBar - Cross-Object-Links nutzen
@exportoder Editor-Signal-Connect — nicht/root/... - Akzeptieren durch Reparenting von Player und Beobachten der Bar — nicht durch „Skript OK generiert“
Sie haben jetzt ein einfügbares Godot-MCP-Prompt-Regelwerk; Inventar, Quest-Log und Kill-Counter können dasselbe Muster wiederverwenden.
Weiterlesen
Weitere Guides, die Sie interessieren könnten
Game-UI-Design: Traditioneller Workflow vs. KI-Grafik + VberAI Studio-Aufteilung
PS/Figma manuelles Slicing vs. VberAI Studio: UI importieren oder KI-generieren, Layer automatisch trennen, PSD oder Bildsets exportieren. Effekte, Schritte, Demos.
- game-ui-design
- game-ui-designer-flow
- ui-slicing
- AIGC
KI-Spiel-UI: Prefab-YAML nicht bearbeiten – nutze das Canvas für den Export nach Unity / Godot / Cocos
Warum LLMs beim KI-Zusammenbau von Spiel-UI kein Prefab-YAML lesen oder schreiben sollten. Middle-Layer-Workflow, deterministischer Export und VberAI Studio Canvas von Figma / PSD zu Unity-, Godot- und Cocos-Prefabs.
- game-ui-design
- game-dev-ai
- ui-to-engine
- figma-to-unity
PSD to Unity UGUI: Photoshop-PSD mit KI schneiden und Prefab bauen
PSD-to-Unity-Prefab-Workflow: Photoshop-PSD in VberAI Studio schneiden, Unity-UGUI-Hierarchie exportieren—Alternative zu reinem PSD2UGUI-Handarbeit.
- vberai
- ai-studio
- psd
- unity