Godot 4:シグナル規約をプロンプトに書いて MCP で HP バーを配線する
Cursor で Godot MCP に指示する前に health_changed シグナル契約を定義し、深い get_node パスなしで HUD を接続する——プロンプトテンプレート、GDScript サンプル、アンチパターン、Play 検収。
- Godot MCP
- Godot 4
- シグナル
- HUD
- GDScript
- Cursor
- AI game development
- tutorial
Godot で最も多い「AI が直したら壊れた」原因は構文エラーではなく、HP バースクリプトにハードコードされたパスです:
$"/root/Game/Player/HitPoints".hp # または get_node("../../Player/...")
シーンを組み替えたり Player を子シーンとしてインスタンス化すると、そのパスは死にます。Godot MCP はプロンプトに忠実に従います——ハードパスを禁止しなければ、モデルは作り続けます。
この記事は一つのことだけ扱います:Cursor(または Claude Code)で先にシグナル契約を示し、MCP にプレイヤー HP を HUD バーへ配線させること。インストール手順やフルプラットフォーマー構築は省略します。
| ステップ | やること |
|---|---|
| 1 | シグナル名・引数・発信者 / 受信者を決める |
| 2 | 制約付きプロンプトで MCP にスクリプトと接続を編集させる |
| 3 | Play で検収;アンチパターンを見てプロンプトを直す |
関連記事:
公式背景:Scene organization — 子シーンは深いパスではなくシグナル / エクスポートで外に公開する。
なぜ「シグナル規約」をプロンプトに書くのか
| やり方 | 短期 | シーン再構成後 |
|---|---|---|
get_node("../Player/Health") | 速い | よく壊れる |
@onready var bar = %HealthBar(ユニーク名) | 同一シーンなら可 | シーン跨ぎでは脆い |
signal health_changed(current, max) + connect | 2 行多い | HUD と Player のツリーを独立して変更可 |
MCP に永続的な「アーキテクチャ記憶」はなく、毎回制約を書かない限りありません。貼り付け可能な契約ブロックは、diff からハードパスを掃除するより安いです。
まず最小ノード骨格を決める
フル UI は不要。v1 にはこれだけ:
Game (Node2D / Node)
├── Player (CharacterBody2D) ← player_health.gd
│ └── ...
└── HUD (CanvasLayer)
└── HealthBar (ProgressBar または TextureProgressBar) ← hud_health.gd
命名:
| ノード | 推奨名 | 備考 |
|---|---|---|
| プレイヤー根 | Player | HP スクリプトを付ける |
| HUD 層 | HUD | CanvasLayer |
| バー | HealthBar | ProgressBar;絶対 HP か max_value = 1 の比率 |
HUD が AI Studio から来た場合、配線前に安定した英語 ID にリネームしてください。
シグナル契約(毎回のプロンプト先頭に貼る)
以下をプロジェクト規約として扱い、指示の先頭に貼ります:
【シグナル契約 — HP】
1. Player 上の HP スクリプトのみが発信:
signal health_changed(current: float, max_health: float)
過去形 / 完了の命名;引数は常に (current, max_health)。
2. HUD バースクリプトはそのシグナルにだけ接続し ProgressBar を更新;HUD から Player へ get_node 禁止。
3. 禁止:シーン跨ぎの深い NodePath、Autoload を HP バスに(本タスクでは不要)、_process で Player をポーリング。
4. 接続はエディタのシグナル接続を優先、または HUD スクリプトで @export NodePath / エクスポート Node 参照で Player を指して connect;"/root/..." のハードコード禁止。
5. ダメージ・回復は Player 側の値だけ変更して emit;UI は HP を変更しない。
このブロックが本記事の核心です:実装より先に規約。
ステップ 1:読み取り専用スモークテスト(MCP がシーンを見えるか)
現在編集中のシーンのルート直下の子ノード名を一覧表示。ファイルやノードは一切変更しない。
Player と HUD(または同等名)が見えてから書き込みます。
ステップ 2:MCP に Player で「発信のみ」を実装させる
プロンプト例(契約の後に続ける):
【シグナル契約 — HP】(上記を全文貼り付け)
res://scripts/player_health.gd(なければ作成)を Player にアタッチ:
- @export var max_health: float = 100.0
- var current: float
- signal health_changed(current: float, max_health: float)
- _ready で current = max_health、health_changed を 1 回 emit
- take_damage(amount)、heal(amount);0..max_health にクランプ;変更のたびに emit
- HUD を参照しない;UI へ get_node しない
保存後、シグナル引数の型を報告。
参考実装(モデル生成後にレビュー可):
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)
一時ダメージキー(本番では削除):
Player に一時的な debug_damage.gd を追加:H キーで同一ノード(または親)の PlayerHealth.take_damage(10) を呼ぶ。配線検収専用。HUD は触らない。
HP スクリプトを Player 根に直接付ける場合、extends Node を根の型に合わせる(例:CharacterBody2D)、または PlayerHealth を子ノード Health にする——どちらかをプロンプトに明記し、MCP にマウント位置を推測させない。
ステップ 3:HUD は購読のみ、エクスポート参照で Player を見つける
【シグナル契約 — HP】(全文貼り付け)
res://scripts/hud_health.gd を HUD または HealthBar に作成:
- @export var player_health: PlayerHealth # または Node を as PlayerHealth
- @onready var bar: ProgressBar = $HealthBar # スクリプトが HUD 上の場合;パスは HUD サブツリー内のみ
- _ready: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
(0..1 比率のみ:bar.max_value = 1;bar.value = current / max_health)
- Player へ get_node 禁止;/root 絶対パス禁止
次に:エディタでエクスポート player_health を Player の PlayerHealth(または Health 子)に割り当て。シーンを保存。
参考実装:
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
HUD 内部の $HealthBar は問題なし——同一サブツリー。禁止なのは Player へ跨る深いパスです。
エディタの「ノード → シグナルを接続」も MCP で可。プロンプトに明記:
エディタでシグナル接続:Player(PlayerHealth)の health_changed → HUD スクリプトの _on_health_changed。NodePath 文字列を手書きしない。
ステップ 4:Play 検収チェックリスト
- シーン入場時:バー満タン(または正しい比率)
- H 押下:
bar.valueが下がる - 0 まで:バー空;死亡ロジックがあっても UI が
currentを書き換えない heal後:バーが上がるPlayerをより深い子(例:Entities)にリペアレントして再 Play:エクスポート参照が残っていればバーは更新される——ハードパスに対する核心の利点
リペアレント後に切れたら、空のエクスポートを直す——MCP に「別の get_node」を書かせない。
検収プロンプト:
Play モードのエラーから診断:シグナルが発火しないなら connect を確認;player_health が null ならエクスポート参照だけ修正。「修正」に絶対 get_node パスを使わない。先に診断し、編集前に私の OK を待つ。
アンチパターン:これを見たらプロンプトを直す、マージしない
| アンチパターン | 問題 | プロンプトへの追加 |
|---|---|---|
get_node("/root/Game/Player") | ルートパス変更で壊れる | 「/root と絶対 NodePath 禁止」 |
get_parent().get_node("Player") | 兄弟関係への依存 | 「HUD は Player との相対階層を仮定しない」 |
Autoload GlobalHealth.hp | グローバル状態はテスト困難 | 「本タスクで新規 Autoload 禁止」 |
HUD の _process で毎フレーム Player 探索 | 遅く脆い | 「ポーリング禁止;シグナルのみ」 |
シグナル名 update / set_hp | 曖昧、衝突しやすい | 「シグナル名は health_changed 必須」 |
ホットパスの移動や複雑な戦闘計算は手書きが依然有利;HP バー配線はボイラープレートで、契約付き MCP プロンプトの方が通常安い。詳細は Godot MCP vs 手書きスクリプト。
再利用可能な「契約 + タスク」プロンプト骨格
マナバー、ボスバーに差し替えるときはシグナル名とノード名だけ変更:
【シグナル契約】
- 発信者:<ノード/スクリプト>
- signal <name>(...)
- 受信者:<HUD スクリプトメソッド>
- 禁止:絶対 NodePath、Autoload バス、_process ポーリング
【タスク】
1. …
2. …
3. シーンを保存;新規シグナルと接続方法を列挙(エディタ接続 / .connect)
まとめ
- ハードパスは プロンプトの穴であり、「MCP が Godot を知らない」わけではない
- 編集依頼の前に
health_changed(current, max_health)契約を貼る - Player は emit のみ;HUD は connect +
ProgressBar更新のみ - オブジェクト間は
@export参照かエディタシグナル接続——/root/...ではない - 「スクリプト生成成功」ではなく「Player の親を組み替えてもダメージが反映される」で検収
これで貼り付け可能な Godot MCP プロンプト規約ができました。インベントリ、クエストログ、キルカウンターも同じパターンで拡張できます。
続きを読む
こちらの記事もおすすめです
5分で AI Studio を使って PSD を Unity UI に取り込む手順
VberAI Studio による構造を保ったインポートで、レイヤー付き PSD を Unity UI プレハブに素早く変換。Canvas 設定のコツも解説。
- vberai
- ai-studio
- unity
- psd
バトルポップアップ数字:引き継ぎ受け入れとエンジン実装
ポップアップのボケ、欠字、描画順、同屏カクつきの不合格基準。TMPとビットマップ数字の選び方、プールとCanvas順序、Unity UGUIの6ステップ、デザイン数字アートの渡し方。
- game-ui-design
- game-dev-ai
- ui-to-engine
- bitmap-font
AI Studio からエクスポートした HUD を Unity MCP で HP イベントに接続する
AI Studio が Unity HUD プレハブをエクスポートしたあと、Cursor + Unity MCP で HP イベントを購読し、HP バーとダメージ数字を更新。Play モードでの受け入れチェックリストとよくある断点の切り分けも解説します。
- Unity MCP
- AI Studio
- HUD
- Unity