با یک آموزش دیگه بازی سازی با انجین گودو، ساخت داده سفارشی در انجین گودو با شما هستیم. این آموزش پیشرفته است و نیاز به دانستن مقدماتی مثل آشنایی با زبان GD_script و انجین گودو داره. پیشنهاد میکنم برای آشنایی بیشتر، اگر آموزش های قبلی را مشاهده نکردید از اینجا ببینید.
مسئله و راه حل های نامناسب
قبل از هر چیز مسئله رو مشخص کنیم. فرض کنید میخواید در یک مرحله از بازی خودتون 10 تا دشمن داشته باشید و بتونید مشخصات این 10 دشمن رو در ادیتور یکی یکی تعیین کنید. چه راه حلی به ذهنتون میرسه؟ ممکنه بخواید یک آبجکت به نام enemy بسازید و یک class_name هم بهش اختصاص بدید و در یه اسکریپت دیگه استفاده کنید و از export بهره ببرید. ولی با این روش نمیتونید مشخصات هر آبجکت رو توی ادیتور وارد کنید. شاید ترجیح بدید که یه آرایه تعریف کنید و مشخصات هر دشمن بهش بدید. ممکنه کارساز باشه. اما اگه مشخصات دشمن شما متنوع باشه و تعداد زیادی مرحله داشته باشید، آسون تر اینه که توی از ادیتور این کار رو انجام بدید.
راه حل: داده سفارشی
این جاست که تعریف یه نوع داده سفارشی به کارتون میاد. توی این آموزش ما یک داده به نام enemy_data_type تعریف میکنیم. برای اون دو ویژگی health که از نوع int هست و poison یعنی سمی بودن از نوع bool تعریف میکنیم (فرض میکنیم بعضی از دشمن ها سمی ان و بعضی از اونها نیستن). کاری میکنیم که توی ادیتور ین امکان باشه که به طور مستقیم بشه به متغیرهای enemy مقدار داد. و در نهایت یک آرایه از enemy ها میسازیم که در ادیتور قابل تغییر هستن و برای مثال با print یک خروجی میگیریم.
چیزی که دنبالش هستیم اینه:

شروع
بیاید شروع کنیم. یک پروژه جدید بسازید. یک اسکریپت بسازید و محتویاتش رو به شکل زیر وارد کنید:
extends Resource
class_name Enemy_data_type
@export var health:int =10
@export var poison:bool = false
func _init(hlth:=10,psn:=false):
health = hlth
poison = psn
دررابطه با اسکریپت بالا دقت کنید که:
- این اسکریپت از Resource ارث بری کرده.
- یک class_name بهش اختصاص دادیم تا بتونیم در اسکریپت های دیگه به راحتی ازش استفاده کنیم.
- دو متغیر health و poison براش تعریف کردیم و بهشون export اضافه کردیم.
- فانکشن init رو براش پیاده سازی کردیم و دو مقدار ورودی گرفتیم. در عین حال برای اون دو مقدار مقادیر پیشفرض تعیین کردیم که به مشکل برنخوریم.
- در فانکشن init مقدار ورودی تابع رو به متغیرهای enemy دادیم.
حالا میخوایم توی یه صحنه و یه اسکریپت دیگه از این استفاده کنیم. یه صحنه میسازیم و یه اسکریپت بهش اختصاص میدیم. محتویات اسکریپت اینه:
extends Node2D
@export var enemyArray:Array[Enemy_data_type]
func _ready():
print("first enemy health : " + str(enemyArray[0].health))
print("first enemy health : " + str(enemyArray[0].poison
توضیحات اسکریپت:
- یک متغیر به نام enemyArray تعریف و export کردیم. این متغیر از آرایه ای از نوع داده enemy_data_type ئه که ما تعریف کردیم. این خط باعث میشه که توی ادیتور به مقادیر دسترسی داشته باشیم.(هدف اصلی این تمرین)
- در فانکشن ready اولین عضو از آرایه enemyArray رو گرفتیم و متغیرهای اون، health و poison رو چاپ کردیم.
اینجا نود اصلی صحنه رو انتخاب میکنیم و در ادیتور میبینیم که فیلد enemy array اضافه شده. بعد تعداد و مقادیر دلخواه رو برای دشمن ها وارد میکنیم.

صحنه رو اجرا کنید. خروجی در کنسول انجین این خواهد بود:
first enemy health : 10
first enemy health : true
میبینید که مشخصات اولین دشمن رو که ما در ادیتور وارد کرده بودیم بهمون برگردوند.
با این روش آشنا بودید؟ به نظرتون کجاها میتونید ازش استفاده کنید؟