← العودة إلى المدونة

Godot 4: ضع قواعد الإشارات في موجهك حتى يقوم MCP بتوصيل شريط الصحة

قبل أن تطلب من Godot MCP في Cursor، حدد عقد إشارة health_changed حتى يتصل HUD دون مسارات get_node العميقة—قوالب موجه، أمثلة GDScript، أنماط مضادة، وقبول Play.

نُشر في
  • Godot MCP
  • Godot 4
  • signals
  • HUD
  • GDScript
  • Cursor
  • AI game development
  • tutorial

الخطأ الأكثر شيوعًا في Godot الذي “يكسر مشهدي” ليس خطأ في بناء الجملة—بل هو سكربت شريط الصحة الذي يرمّز المسارات بشكل ثابت:

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

أعد ترتيب الشجرة أو اجعل Player مشهدًا فرعيًا، وسيموت هذا المسار. Godot MCP يتبع موجهك بأمانة—إذا لم تمنع المسارات الثابتة، سيستمر النموذج في اختراعها.

هذه المقالة تقوم بمهمة واحدة: في Cursor (أو Claude Code)، حدد عقد إشارة أولاً، ثم دع MCP يربط صحة اللاعب بشريط HUD. لا يوجد دليل تثبيت، ولا بناء منصة كامل.

الخطوةما تفعله
1اسم الإشارة، الوسائط، المُرسِل / المُستقبِل
2وجّه MCP بالقيود لتحرير السكربتات والاتصالات
3اقبل في Play؛ أصلح الموجه باستخدام الأنماط المضادة

ذات صلة:

خلفية: تنظيم المشهد — يجب أن تعرض المشاهد الفرعية إشارات / تصديرات، وليس مسارات عميقة.

لماذا تنتمي قواعد الإشارات إلى الموجه

النهجالمدى القصيربعد إعادة التنظيم
get_node("../Player/Health")سريعغالبًا ما ينكسر
@onready var bar = %HealthBar (اسم فريد)جيد في مشهد واحدلا يزال هشًا عبر المشاهد
signal health_changed(current, max) + connectسطران إضافيانيمكن لشجرتي HUD وPlayer التغير بشكل مستقل

ليس لدى MCP “ذاكرة معمارية” دائمة إلا إذا كررت القيود. كتلة عقد قابلة للصق أرخص من تنظيف المسارات الثابتة من كل فرق.

هيكل العقد الأدنى

لا تحتاج إلى واجهة كاملة. الإصدار الأول يحتاج فقط:

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

التسمية:

العقدةالاسم المقترحملاحظات
جذر PlayerPlayerيملك سكربت الصحة
طبقة HUDHUDCanvasLayer
الشريطHealthBarProgressBar؛ HP مطلق أو max_value = 1 نسبة

إذا جاء HUD من AI Studio، أعد تسميته إلى معرفات إنجليزية مستقرة قبل التوصيل.

عقد الإشارة (الصقه في أعلى كل موجه)

عامل هذا كقانون مشروع:

[عقد الإشارة — الصحة]
1. فقط سكربت الصحة على Player يُصدر:
   signal health_changed(current: float, max_health: float)
   تسمية الماضي التام / المكتمل؛ الوسائط دائمًا (current, max_health).
2. سكربت شريط HUD يتصل فقط بتلك الإشارة ويحدّث ProgressBar؛ لا get_node إلى Player من HUD.
3. ممنوع: مسارات NodePath عميقة عبر المشاهد، Autoload كحافلة صحة (ليست مطلوبة هنا)، استطلاع Player في _process.
4. يُفضل اتصالات الإشارة في المحرر، أو @export Node / NodePath على HUD ثم .connect — لا ترمّز أبدًا "/root/...".
5. الضرر والشفاء يغيران القيم فقط على Player ويُصدران؛ لا تغيّر الواجهة HP أبدًا.

هذه الكتلة هي نقطة هذه المقالة: العقد قبل التنفيذ.

الخطوة 1: اختبار قراءة فقط

اذكر أسماء الأطفال تحت جذر المشهد المُحرَّر حاليًا. لا تعدّل أي ملفات أو عقد.

اكتب فقط عندما ترى Player و HUD (أو ما يعادلهما).

الخطوة 2: Player يُصدر فقط

أضف بعد العقد:

[عقد الإشارة — الصحة] (الصق الكتلة الكاملة)

في 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 مرة واحدة
- take_damage(amount), heal(amount); اقصره على 0..max_health; أرسل بعد كل تغيير
- لا تشير إلى HUD؛ لا تستخدم 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)

مفتاح ضرر مؤقت (احذفه لاحقًا):

أضف debug_damage.gd مؤقتًا على Player: الضغط على H يستدعي PlayerHealth.take_damage(10) على نفس العقدة (أو الأصل). قبول التوصيل فقط. لا تلمس HUD.

إذا كان السكربت على جذر Player، غيّر extends Node ليطابق (مثل CharacterBody2D)، أو اجعل PlayerHealth طفلًا Health—اختر واحدًا في الموجه حتى لا يخمن MCP نقطة التركيب.

الخطوة 3: HUD يشترك عبر مرجع مُصدَّر

[عقد الإشارة — الصحة] (الصق الكتلة الكاملة)

أنشئ res://scripts/hud_health.gd على HUD أو HealthBar:
- @export var player_health: PlayerHealth
- @onready var bar: ProgressBar = $HealthBar  # فقط إذا كان السكربت على HUD؛ المسار يبقى داخل شجرة 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
  (أو نسبة: max_value = 1; value = current / max_health)
- ممنوع: get_node إلى Player؛ ممنوع: مسارات /root المطلقة
ثم عيّن player_health المُصدَّر إلى PlayerHealth الخاص بـ Player (أو طفل Health) في المحرر. احفظ المشهد.

المرجع:

extends CanvasLayer

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

func _ready() -> void:
	assert(player_health != null, "عيّن PlayerHealth في المفتش")
	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 داخل HUD مقبول—نفس الشجرة الفرعية. الممنوع هو مسار عميق عبر إلى Player.

اتصال “العقدة → اتصال إشارة” في المحرر عبر MCP مقبول أيضًا:

اتصل عبر المحرر: Player (PlayerHealth) health_changed → سكربت HUD _on_health_changed. لا تكتب سلاسل NodePath يدويًا.

الخطوة 4: قائمة قبول Play

  1. عند الدخول: الشريط ممتلئ (أو النسبة الصحيحة)
  2. اضغط H: bar.value ينخفض
  3. إلى 0: الشريط فارغ؛ يجب ألا تكتب الواجهة current
  4. بعد heal: الشريط يرتفع
  5. أعد ترتيب Player تحت مثل Entities وشغّل Play مرة أخرى: الشريط لا يزال يتحدث إذا بقي مرجع التصدير—هذا هو الفوز مقابل المسارات الثابتة

إذا انكسر بعد إعادة الترتيب، أصلح التصدير الفارغ—لا تطلب من MCP “get_node آخر”.

موجه القبول:

شخّص من أخطاء Play: إذا لم تُطلق الإشارة أبدًا، تحقق من الاتصال؛ إذا كان player_health فارغًا، أصلح التصدير فقط. لا "تصلح" بمسارات get_node المطلقة. شخّص أولاً؛ انتظر موافقتي قبل التحرير.

الأنماط المضادة: غيّر الموجه، لا تدمج

النمط المضادلماذا يضرأضف إلى الموجه
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”

الكتابة اليدوية لا تزال تفوز في حركة المسار الساخن وحسابات القتال المعقدة؛ توصيل شريط الصحة هو كود روتيني حيث يكون موجه MCP المتعاقد عليه أرخص عادةً. انظر Godot MCP مقابل البرمجة اليدوية.

هيكل “عقد + مهمة” قابل لإعادة الاستخدام

بدّل الأسماء لشرائط المانا / الزعيم:

[عقد الإشارة]
- المُرسِل: <عقدة/سكربت>
- الإشارة: <name>(...)
- المُستقبِل: <طريقة HUD>
- ممنوع: NodePath مطلق، حافلة Autoload، استطلاع _process

[المهمة]
1. …
2. …
3. احفظ المشهد؛ اذكر الإشارات الجديدة وكيف تتصل (محرر / .connect)

الملخص

  1. المسارات الثابتة هي ثغرة في الموجه، وليست “MCP لا يفهم Godot”
  2. الصق health_changed(current, max_health) قبل طلب التعديلات
  3. Player يُصدر فقط؛ HUD يتصل فقط ويحدّث ProgressBar
  4. الروابط عبر الكائنات تستخدم @export أو اتصال إشارة المحرر—ليس /root/...
  5. اقبل بإعادة ترتيب Player ومشاهدة الشريط—ليس بـ “تم إنشاء السكربت بنجاح”

لديك الآن مجموعة قواعد موجه Godot MCP قابلة للصق؛ يمكن للمخزون وسجل المهام وعدادات القتل إعادة استخدام نفس النمط.

أدلة أخرى قد تعجبك

تصميم واجهة اللعبة: سير العمل التقليدي مقابل فن الذكاء الاصطناعي + تقسيم VberAI Studio

قارن التقطيع اليدوي في PS/Figma مع VberAI Studio: استيراد أو توليد الواجهة بالذكاء الاصطناعي، تقسيم الطبقات تلقائياً، تصدير PSD طبقية أو مجموعات صور. التأثيرات والخطوات وفيديوهات العرض.

  • game-ui-design
  • game-ui-designer-flow
  • ui-slicing
  • AIGC
اقرأ المزيد