Unity Editor'da Tam Sayı Girişi: `EditorGUILayout.IntField()` Kullanımı
Unity, oyun geliştiricilere güçlü bir oyun motoru sunarken, aynı zamanda geliştirme sürecini kişiselleştirmek için kapsamlı araçlar sağlar. Bu araçlardan en önemlilerinden biri de özel Inspector'lar ve genel olarak Unity Editor uzantıları oluşturma yeteneğidir. Kendi özel Inspector'larınızı yazarak, oyun nesnelerinizin veya ScriptableObject'lerinizin verilerini daha düzenli, okunabilir ve işlevsel bir şekilde yönetebilirsiniz. Bu makalede, bu tür özel Inspector'larda sıklıkla ihtiyaç duyulan tam sayı (integer) girişlerini sağlamak için kullanılan `EditorGUILayout.IntField()` metodunu detaylı bir şekilde inceleyeceğiz.
EditorGUILayout.IntField(), Unity Editor'da bir tam sayı değeri girmek için kullanılan bir kontrol elemanıdır. Standart Inspector'da gördüğünüz int alanlarına benzer bir görünüm ve işlevsellik sunar, ancak bunu kendi özel Inspector'larınızda kullanmanıza olanak tanır. Bu sayede, geliştiriciler kendi araçlarını oluştururken kullanıcı dostu arayüzler tasarlayabilirler.
EditorGUILayout.IntField() Temelleri
Özel bir Inspector oluşturmak için öncelikle Unity'nin Editor klasörü içinde bir C# script oluşturmanız gerekir. Bu script, hedeflediğiniz `MonoBehaviour` veya `ScriptableObject` sınıfına ait verileri Inspector'da gösterecek ve değiştirecektir.
Adım 1: Hedef Script'i Oluşturma
Öncelikle, özel Inspector'umuzun kontrol edeceği basit bir `MonoBehaviour` script'i oluşturalım. Örneğin, bir oyun karakterinin can puanını veya bir eşyanın miktarını tutan bir script olabilir:
// Assets/Scripts/PlayerStats.cs
using UnityEngine;
public class PlayerStats : MonoBehaviour
{
public int maxHealth = 100;
public int currentAmmo = 30;
}
Adım 2: Özel Editor Script'ini Oluşturma
Şimdi bu `PlayerStats` script'i için özel bir Inspector oluşturalım. Editor script'leri her zaman projenizdeki Assets/Editor klasörü içinde olmalıdır. Bu klasördeki script'ler oyun derlemesine dahil edilmez, sadece Unity Editor'da çalışır.
// Assets/Editor/PlayerStatsEditor.cs
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(PlayerStats))]
public class PlayerStatsEditor : Editor
{
public override void OnInspectorGUI()
{
// Hedef script'in referansını alıyoruz
PlayerStats playerStats = (PlayerStats)target;
// maxHealth alanını EditorGUILayout.IntField ile çiziyoruz
playerStats.maxHealth = EditorGUILayout.IntField("Maksimum Can", playerStats.maxHealth);
// currentAmmo alanını da çizelim
playerStats.currentAmmo = EditorGUILayout.IntField("Mevcut Mühimmat", playerStats.currentAmmo);
// Değişikliklerin kaydedildiğinden emin olmak için
if (GUI.changed)
{
EditorUtility.SetDirty(playerStats);
}
}
}
Yukarıdaki kodda dikkat etmemiz gerekenler:
using UnityEditor;: Editor sınıflarını kullanmak için bu namespace'i dahil etmeliyiz.[CustomEditor(typeof(PlayerStats))]: Bu nitelik (attribute), Unity'ye bu Editor script'inin hangi `MonoBehaviour` veya `ScriptableObject` sınıfı için özel bir Inspector sağlayacağını bildirir.public class PlayerStatsEditor : Editor: Özel Editor script'imiz mutlaka `UnityEditor.Editor` sınıfından türemelidir.public override void OnInspectorGUI(): Bu metot, Unity Inspector penceresi her çizildiğinde çağrılır. Tüm özel Inspector arayüz kodumuz buraya yazılır.PlayerStats playerStats = (PlayerStats)target;: `target` özelliği, özel Inspector'ın kontrol ettiği `MonoBehaviour` veya `ScriptableObject` örneğine bir referanstır. Bu referansı kendi script'imizin türüne dönüştürerek değişkenlerine erişebiliriz.EditorGUILayout.IntField("Maksimum Can", playerStats.maxHealth);: Bu satır, Inspector'da "Maksimum Can" etiketli bir tam sayı giriş alanı oluşturur. İlk parametre etiketi, ikinci parametre ise başlangıç değeridir. Kullanıcı giriş yaptığında, yeni değer `playerStats.maxHealth`'e atanır.if (GUI.changed) { EditorUtility.SetDirty(playerStats); }: Bu kontrol, Inspector'da bir değişiklik yapıldığında Unity'ye bu objenin değiştiğini bildirir ve değişikliklerin kaydedilmesini sağlar. Özellikle sahne dışındaki (prefab gibi) varlıklar için bu çok önemlidir.
EditorGUILayout sınıfı, Editor arayüz elemanlarını otomatik olarak düzenleyen (layout) metotlar sunar. Eğer daha hassas konumlandırma ve boyutlandırma kontrolüne ihtiyacınız varsa, `EditorGUI` sınıfını kullanabilirsiniz. Ancak çoğu durumda `EditorGUILayout` daha pratik ve yeterlidir.
Gelişmiş Kullanım ve İpuçları
İpucu 1: Geri Alma (Undo) İşlemlerini Destekleme
Kullanıcıların yaptıkları değişiklikleri geri alabilmeleri, iyi bir Editor deneyiminin vazgeçilmezidir. `Undo.RecordObject()` metodu ile bu desteği kolayca sağlayabiliriz:
public override void OnInspectorGUI()
{
PlayerStats playerStats = (PlayerStats)target;
// Değişiklik yapmadan önce objenin mevcut durumunu kaydet
Undo.RecordObject(playerStats, "Change Player Stats");
playerStats.maxHealth = EditorGUILayout.IntField("Maksimum Can", playerStats.maxHealth);
playerStats.currentAmmo = EditorGUILayout.IntField("Mevcut Mühimmat", playerStats.currentAmmo);
if (GUI.changed)
{
EditorUtility.SetDirty(playerStats);
}
}
Artık kullanıcılar Ctrl+Z (Cmd+Z) ile Inspector'da yaptıkları değişiklikleri geri alabilirler.
İpucu 2: Değişiklikleri Algılama ve Koşullu Güncelleme
Bazen Inspector'da sadece belirli bir alanda değişiklik olduğunda özel bir işlem yapmak isteyebiliriz. Ya da performans için sadece değişiklik olduğunda `EditorUtility.SetDirty()` çağırmak isteyebiliriz. `EditorGUI.BeginChangeCheck()` ve `EditorGUI.EndChangeCheck()` metotları bu konuda bize yardımcı olur:
public override void OnInspectorGUI()
{
PlayerStats playerStats = (PlayerStats)target;
Undo.RecordObject(playerStats, "Change Player Stats");
// Değişiklik kontrolünü başlat
EditorGUI.BeginChangeCheck();
playerStats.maxHealth = EditorGUILayout.IntField("Maksimum Can", playerStats.maxHealth);
playerStats.currentAmmo = EditorGUILayout.IntField("Mevcut Mühimmat", playerStats.currentAmmo);
// Değişiklik oldu mu?
if (EditorGUI.EndChangeCheck())
{
Debug.Log("PlayerStats'ta bir değer değiştirildi!");
EditorUtility.SetDirty(playerStats);
// Örneğin, maxHealth 0'dan küçükse 0 yap gibi ek kontroller ekleyebilirsiniz.
if (playerStats.maxHealth < 0) playerStats.maxHealth = 0;
}
}
Bu yöntem, yalnızca bir değişiklik tespit edildiğinde ilgili işlemleri yapmanızı sağlayarak gereksiz güncellemelerin önüne geçer.
İpucu 3: Minimum/Maksimum Değer Sınırlamaları
EditorGUILayout.IntField() doğrudan bir min/max değer sınırlaması sunmaz. Ancak bunu kendiniz kolayca uygulayabilirsiniz:
// ... OnInspectorGUI içinde ...
playerStats.maxHealth = EditorGUILayout.IntField("Maksimum Can (0-100)", playerStats.maxHealth);
playerStats.maxHealth = Mathf.Clamp(playerStats.maxHealth, 0, 100); // Değeri 0-100 arasına sıkıştır
playerStats.currentAmmo = EditorGUILayout.IntField("Mevcut Mühimmat (>=0)", playerStats.currentAmmo);
playerStats.currentAmmo = Mathf.Max(0, playerStats.currentAmmo); // Değeri en az 0 yap
// ...
Bu, kullanıcıların geçersiz değerler girmesini engellemenize yardımcı olur.
İpucu 4: SerializedProperty ile Daha Sağlam Editor'lar
Daha karmaşık ve sağlam Unity Editor uzantıları yazarken, doğrudan `target` objesinin değişkenlerine erişmek yerine `SerializedProperty` kullanmak daha iyi bir yaklaşımdır. Bu, özellikle prefab'lerle çalışırken ve Unity'nin serialization sistemiyle daha uyumlu olmanızı sağlar.
public class PlayerStatsEditor : Editor
{
SerializedProperty maxHealthProp;
SerializedProperty currentAmmoProp;
void OnEnable()
{
// Editor açıldığında veya script yeniden derlendiğinde property'leri bul
maxHealthProp = serializedObject.FindProperty("maxHealth");
currentAmmoProp = serializedObject.FindProperty("currentAmmo");
}
public override void OnInspectorGUI()
{
// Tüm değişiklikleri kaydetmek için serializedObject'i güncelle
serializedObject.Update();
// SerializedProperty ile IntField kullanma
EditorGUILayout.PropertyField(maxHealthProp, new GUIContent("Maksimum Can"));
EditorGUILayout.PropertyField(currentAmmoProp, new GUIContent("Mevcut Mühimmat"));
// Değişiklikleri serializedObject'e uygula
serializedObject.ApplyModifiedProperties();
}
}
Bu yöntem, `Undo` işlemlerini ve prefab override'larını otomatik olarak yönetir. `EditorGUILayout.PropertyField` metodu, uygun Editor alanı türünü (bu durumda `IntField`) otomatik olarak çizer.
Yaygın Hatalar ve Çözümleri
- Değişikliklerin Kaydedilmemesi: `EditorUtility.SetDirty(target);` veya `serializedObject.ApplyModifiedProperties();` kullanmayı unutmak, Editor'da yaptığınız değişikliklerin Unity tarafından kalıcı olarak kaydedilmemesine neden olabilir. Özellikle prefab'ler üzerinde çalışırken bu hatayla sıkça karşılaşılır.
- `Editor` Sınıfından Türetmeme: Özel Editor script'inizin `UnityEditor.Editor` sınıfından türediğinden emin olun. Aksi takdirde, Unity onu bir Editor script'i olarak tanımaz.
- `OnInspectorGUI` Dışında `EditorGUILayout` Kullanımı: `EditorGUILayout` metotları sadece `OnInspectorGUI()` içinde veya bu metot tarafından çağrılan diğer metotlar içinde kullanılmalıdır. Aksi takdirde hatalar alırsınız.
- `Assets/Editor` Klasörünü Unutmak: Editor script'lerinizin sadece Editor'da çalışması ve oyun derlemesine dahil edilmemesi için mutlaka `Assets/Editor` veya alt klasörlerinde bulunması gerekir.
- `UnityEditor` Namespace'ini İçermemek: `using UnityEditor;` satırını eklemeyi unutmayın.
Performans ve Optimizasyon Notları
`OnInspectorGUI()` metodu, Inspector penceresi her yeniden çizildiğinde (fare hareketleri, klavye girişi, animasyonlar vb.) çağrılır. Bu nedenle, bu metot içinde ağır hesaplamalar yapmaktan kaçınmak önemlidir. `EditorGUI.BeginChangeCheck()` ve `EditorGUI.EndChangeCheck()` kullanarak sadece gerçekten bir değer değiştiğinde pahalı işlemleri tetiklemek, Editor'ınızın performansını artıracaktır. Gereksiz yere `GetComponent` veya `FindObjectOfType` gibi pahalı API çağrılarından kaçının; bu tür referansları `OnEnable()` metodunda önceden alın.
Özetle, `EditorGUILayout.IntField()` ve genel olarak Unity Editor uzantıları, geliştirme sürecinizi kişiselleştirerek çok daha verimli ve keyifli hale getiren güçlü araçlardır. Bu makaledeki bilgilerle kendi özel Inspector'larınızı oluşturmaya başlayabilir ve Unity iş akışınızı kendi ihtiyaçlarınıza göre şekillendirebilirsiniz.
🧠 Ders Sonu Değerlendirme Testi
Dersi tamamladıktan sonra bilgilerinizi test edin ve ekstra puanlar kazanın.
Yorumlar (0)
İlk yorumu siz yapın!