← Kembali ke blog

Godot 4: Letakkan Aturan Sinyal dalam Prompt Anda agar MCP Menghubungkan Health Bar

Sebelum meminta Godot MCP di Cursor, tentukan kontrak sinyal health_changed agar HUD terhubung tanpa jalur get_node yang dalam—template prompt, contoh GDScript, anti-pattern, dan penerimaan Play.

Diterbitkan
  • Godot MCP
  • Godot 4
  • signals
  • HUD
  • GDScript
  • Cursor
  • AI game development
  • tutorial

Kegagalan paling umum “AI merusak scene saya” di Godot bukanlah kesalahan sintaks—melainkan skrip health bar yang meng-hard-code:

$"/root/Game/Player/HitPoints".hp  # atau get_node("../../Player/...")

Reparent pohon atau instance Player sebagai child scene, dan jalur itu mati. Godot MCP mengikuti prompt Anda dengan setia—jika Anda tidak melarang jalur keras, model akan terus menciptakannya.

Posting ini melakukan satu tugas: di Cursor (atau Claude Code), nyatakan kontrak sinyal terlebih dahulu, lalu biarkan MCP menghubungkan kesehatan pemain ke bar HUD. Tanpa panduan instalasi, tanpa membangun platformer lengkap.

LangkahApa yang Anda lakukan
1Beri nama sinyal, argumen, pengirim / penerima
2Prompt MCP dengan batasan untuk mengedit skrip dan koneksi
3Terima di Play; perbaiki prompt menggunakan anti-pattern

Terkait:

Latar belakang: Organisasi scene — scene anak harus mengekspos sinyal / ekspor, bukan jalur dalam.

Mengapa aturan sinyal termasuk dalam prompt

PendekatanJangka pendekSetelah reorganisasi
get_node("../Player/Health")CepatSering rusak
@onready var bar = %HealthBar (nama unik)Baik dalam satu sceneMasih rapuh antar scene
signal health_changed(current, max) + connectDua baris tambahanPohon HUD dan Player dapat berubah secara independen

MCP tidak memiliki “memori arsitektur” yang bertahan lama kecuali Anda mengulangi batasan. Blok kontrak yang dapat ditempel lebih murah daripada membersihkan jalur keras dari setiap diff.

Kerangka node minimal

Anda tidak perlu UI lengkap. v1 hanya perlu:

Game (Node2D / Node)
├── Player (CharacterBody2D)  ← player_health.gd
│   └── ...
└── HUD (CanvasLayer)
    └── HealthBar (ProgressBar atau TextureProgressBar)  ← hud_health.gd

Penamaan:

NodeNama yang disarankanCatatan
Root PlayerPlayerMemiliki skrip kesehatan
Lapisan HUDHUDCanvasLayer
BarHealthBarProgressBar; HP absolut atau max_value = 1 rasio

Jika HUD berasal dari AI Studio, ganti nama menjadi ID Inggris yang stabil sebelum menghubungkan.

Kontrak sinyal (tempel di atas setiap prompt)

Anggap ini sebagai hukum proyek:

[Kontrak sinyal — kesehatan]
1. Hanya skrip kesehatan di Player yang memancarkan:
   signal health_changed(current: float, max_health: float)
   Penamaan lampau / selesai; argumen selalu (current, max_health).
2. Skrip bar HUD hanya menghubungkan sinyal itu dan memperbarui ProgressBar; tidak ada get_node ke Player dari HUD.
3. Terlarang: NodePath lintas scene yang dalam, Autoload sebagai bus kesehatan (tidak diperlukan di sini), polling untuk Player di _process.
4. Prefer koneksi sinyal editor, atau @export Node / NodePath di HUD lalu .connect — jangan pernah hard-code "/root/...".
5. Damage dan heal hanya mengubah nilai di Player dan memancarkan; UI tidak pernah mengubah HP.

Blok itu adalah inti artikel ini: kontrak sebelum implementasi.

Langkah 1: Uji asap hanya-baca

Daftar nama anak di bawah root scene yang sedang diedit. Jangan ubah file atau node apa pun.

Hanya tulis setelah Anda melihat Player dan HUD (atau yang setara).

Langkah 2: Player hanya memancarkan

Tambahkan setelah kontrak:

[Kontrak sinyal — kesehatan] (tempel blok lengkap)

Di res://scripts/player_health.gd (buat jika belum ada) dan lampirkan ke Player:
- @export var max_health: float = 100.0
- var current: float
- signal health_changed(current: float, max_health: float)
- Di _ready: current = max_health; emit health_changed sekali
- take_damage(amount), heal(amount); clamp 0..max_health; emit setelah setiap perubahan
- Jangan referensikan HUD; jangan get_node ke UI
Simpan dan laporkan tipe argumen sinyal.

Implementasi referensi:

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)

Kunci damage sementara (hapus nanti):

Tambahkan debug_damage.gd sementara di Player: menekan H memanggil PlayerHealth.take_damage(10) pada node yang sama (atau induk). Hanya untuk penerimaan wiring. Jangan sentuh HUD.

Jika skrip berada di root Player, ubah extends Node agar sesuai (mis. CharacterBody2D), atau jadikan PlayerHealth sebagai anak Health—pilih salah satu dalam prompt agar MCP tidak menebak titik pemasangan.

Langkah 3: HUD berlangganan melalui referensi ekspor

[Kontrak sinyal — kesehatan] (tempel blok lengkap)

Buat res://scripts/hud_health.gd di HUD atau HealthBar:
- @export var player_health: PlayerHealth
- @onready var bar: ProgressBar = $HealthBar  # hanya jika skrip di HUD; jalur tetap di dalam subtree 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
  (atau rasio: max_value = 1; value = current / max_health)
- Terlarang: get_node ke Player; terlarang: jalur absolut /root
Kemudian tetapkan player_health yang diekspor ke PlayerHealth Player (atau anak Health) di editor. Simpan scene.

Referensi:

extends CanvasLayer

@export var player_health: PlayerHealth
@onready var bar: ProgressBar = $HealthBar

func _ready() -> void:
	assert(player_health != null, "Tetapkan PlayerHealth di 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 di dalam HUD tidak masalah—subtree yang sama. Yang terlarang adalah jalur dalam lintas ke Player.

Editor “Node → Connect a Signal” melalui MCP juga baik:

Hubungkan melalui editor: Player (PlayerHealth) health_changed → skrip HUD _on_health_changed. Jangan tulis string NodePath secara manual.

Langkah 4: Daftar penerimaan Play

  1. Saat masuk: bar penuh (atau rasio yang benar)
  2. Tekan H: bar.value turun
  3. Ke 0: bar kosong; UI tidak boleh menulis current
  4. Setelah heal: bar naik
  5. Reparent Player di bawah mis. Entities dan Play lagi: bar masih diperbarui jika referensi ekspor tetap ada—itulah kemenangan vs jalur keras

Jika rusak setelah reparent, perbaiki ekspor yang kosong—jangan minta MCP untuk “get_node lain”.

Prompt penerimaan:

Diagnosis dari kesalahan Play: jika sinyal tidak pernah menyala, periksa connect; jika player_health null, hanya perbaiki ekspor. Jangan "perbaiki" dengan jalur get_node absolut. Diagnosis dulu; tunggu OK saya sebelum mengedit.

Anti-pattern: ubah prompt, jangan gabungkan

Anti-patternMengapa merugikanTambahkan ke prompt
get_node("/root/Game/Player")Perubahan root path”Tidak ada /root atau NodePath absolut”
get_parent().get_node("Player")Kopling saudara”HUD tidak boleh mengasumsikan tata letak saudara Player”
Autoload GlobalHealth.hpLaci global berantakan”Tidak ada Autoload baru untuk tugas ini”
HUD _process mencari PlayerLambat dan rapuh”Tidak ada polling; sinyal saja”
Sinyal bernama update / set_hpTidak jelas, rawan bentrok”Sinyal harus health_changed”

Penulisan manual masih menang untuk gerakan hot-path dan matematika combat yang kompleks; wiring health-bar adalah boilerplate di mana prompt MCP yang terkontrak biasanya lebih murah. Lihat Godot MCP vs penulisan skrip manual.

Kerangka “kontrak + tugas” yang dapat digunakan kembali

Ganti nama untuk bar mana / bos:

[Kontrak sinyal]
- Emitter: <node/script>
- signal <name>(...)
- Receiver: <metode HUD>
- Terlarang: NodePath absolut, bus Autoload, polling _process

[Tugas]
1. …
2. …
3. Simpan scene; daftar sinyal baru dan bagaimana mereka terhubung (editor / .connect)
  1. Jalur keras adalah lubang prompt, bukan “MCP tidak bisa Godot”
  2. Tempel health_changed(current, max_health) sebelum meminta edit
  3. Player hanya memancarkan; HUD hanya menghubungkan dan memperbarui ProgressBar
  4. Tautan antar objek menggunakan @export atau connect sinyal editor—bukan /root/...
  5. Terima dengan reparent Player dan melihat bar—bukan dengan “skrip berhasil dibuat”

Anda sekarang memiliki set aturan prompt Godot MCP yang dapat ditempel; inventaris, log pencarian, dan penghitung kill dapat menggunakan pola yang sama.

Panduan lain yang mungkin Anda suka