Unity, oyun geliştiriciler için güçlü ve esnek bir platform sunar. Ancak bazen varsayılan Inspector arayüzü, karmaşık veri yapılarını yönetmek veya geliştirici deneyimini optimize etmek için yeterli olmayabilir. İşte tam bu noktada Custom Inspector ve Property Drawers devreye girer. Bu makalede, Unity editörünüzü nasıl kendi ihtiyaçlarınıza göre özelleştirebileceğinizi, geliştirme sürecinizi nasıl hızlandırabileceğinizi ve ekip içi iletişimi nasıl güçlendirebileceğinizi detaylıca inceleyeceğiz.
Custom Inspector ve Property Drawers, Unity’nin editör genişletme API’sinin temel taşlarındandır. Bu araçlar sayesinde, Component’lerinizin veya ScriptableObject’lerinizin Inspector’da nasıl görüneceğini tamamen kontrol edebilir, özel veri tipleriniz için daha anlamlı ve kullanıcı dostu arayüzler oluşturabilirsiniz.
Neden Custom Inspector Kullanmalıyız?
Unity geliştiricileri için Custom Inspector kullanmanın birçok avantajı vardır. Bu avantajlar, sadece estetik iyileştirmelerden öte, doğrudan geliştirme verimliliği ve hata azaltma üzerinde etkilidir.
1. Kullanıcı Deneyimi İyileştirme
Özellikle büyük projelerde, karmaşık Component’lerin çok sayıda ayarı olabilir. Varsayılan Inspector, bu ayarları alt alta sıralarken, Custom Inspector ile gruplandırma, sekmeler, özel düğmeler veya görsel geri bildirimler ekleyerek daha temiz ve anlaşılır bir arayüz sunabilirsiniz. Bu, geliştiricilerin aradıkları ayarları daha hızlı bulmalarına ve Component’lerle daha sezgisel bir şekilde etkileşime geçmelerine olanak tanır.
2. Hata Azaltma ve Doğrulama
Custom Inspector’lar, kullanıcı girişini anında doğrulama yeteneği sunar. Örneğin, bir değerin belirli bir aralıkta olup olmadığını kontrol edebilir, geçersiz girişlerde uyarı mesajları gösterebilir veya hatta hatalı değerleri otomatik olarak düzeltebilirsiniz. Bu, oyun içinde beklenmedik davranışlara yol açabilecek potansiyel hataları editör aşamasında yakalamanıza yardımcı olur ve geliştirme sürecinde zaman kazandırır.
3. Verimlilik Artırma
Tekrarlayan görevleri veya karmaşık hesaplamaları Inspector’a entegre edebilirsiniz. Örneğin, bir seviye tasarımcısı için karmaşık matematiksel formüller gerektiren bir nesne konumlandırma aracını Inspector içine yerleştirebilirsiniz. Bu, tasarımcıların kod yazmaya gerek kalmadan, doğrudan Inspector üzerinden güçlü araçları kullanabilmesini sağlar ve iş akışını önemli ölçüde hızlandırır.
4. Karmaşık Veri Yapılarını Yönetme
Array’ler, List’ler veya özel sınıf türleri gibi karmaşık veri yapıları, varsayılan Inspector’da genellikle düz ve okunaksız bir şekilde görüntülenir. Custom Inspector veya Property Drawers kullanarak bu yapıları daha düzenli, katlanabilir menülerle veya özel görselleştirmelerle sunabilirsiniz. Bu, özellikle oyununuzun veri odaklı kısımlarını yönetirken büyük kolaylık sağlar.
Custom Inspector Temelleri: Editor Sınıfı
Bir MonoBehaviour veya ScriptableObject için kendi Inspector’ınızı yazmak istediğinizde, UnityEditor.Editor sınıfından türeyen bir sınıf oluşturmanız gerekir. Bu sınıf, ilgili Component’in Inspector’da nasıl çizileceğini tanımlar.
İşte temel adımlar ve önemli noktalar:
- Editor Klasörü: Tüm editör script’leri, projenizdeki
Assetsklasörünün altındaki herhangi birEditoradlı klasörde bulunmalıdır. Bu klasör, derlendiğinde oyunun kendisinde yer almaz, sadece Unity Editor’da kullanılır. CustomEditorNiteliği: Editör sınıfınızın hangi Component’e ait olduğunu belirtmek için[CustomEditor(typeof(HedefComponent))]niteliğini kullanırsınız.OnInspectorGUI()Metodu: Bu metot, Unity her karede Inspector’ı çizdiğinde çağrılır. Tüm özel arayüz çizim kodunuzu buraya yazarsınız.SerializedPropertyveEditorGUILayout: Component’inizin değişkenlerine güvenli bir şekilde erişmek ve Unity’nin varsayılan Inspector elemanlarını kullanmak içinSerializedPropertyveEditorGUILayoutsınıflarını kullanırsınız.
Örnek Custom Inspector Uygulaması
Önce basit bir Component oluşturalım:
using UnityEngine;
public class CharacterStats : MonoBehaviour
{
public string characterName;
public int health;
public float speed;
public bool isPlayer;
}
Şimdi bu Component için bir Custom Inspector yazalım:
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(CharacterStats))]
public class CharacterStatsEditor : Editor
{
public override void OnInspectorGUI()
{
// Hedef Component'in değişkenlerini temsil eden SerializedObject'i alıyoruz.
// Bu, Undo/Redo sistemi ve PrefabOverride'lar ile uyumluluk sağlar.
serializedObject.Update(); // Değişiklikleri güncelle
// Başlık
EditorGUILayout.LabelField("Karakter Özellikleri", EditorStyles.boldHeader);
// Varsayılan alanları çizmek yerine kendi alanlarımızı çizelim.
// Karakter Adı
SerializedProperty nameProp = serializedObject.FindProperty("characterName");
EditorGUILayout.PropertyField(nameProp, new GUIContent("Adı"));
// Can ve Hız için özel slider'lar
SerializedProperty healthProp = serializedObject.FindProperty("health");
EditorGUILayout.IntSlider(healthProp, 0, 100, new GUIContent("Can"));
SerializedProperty speedProp = serializedObject.FindProperty("speed");
EditorGUILayout.Slider(speedProp, 0f, 10f, new GUIContent("Hız"));
// Oyuncu mu kontrol kutusu
SerializedProperty isPlayerProp = serializedObject.FindProperty("isPlayer");
EditorGUILayout.PropertyField(isPlayerProp, new GUIContent("Oynanabilir Karakter"));
// Değişiklikleri kaydet
serializedObject.ApplyModifiedProperties();
}
}
Bu örnekte, CharacterStats Component’imizin Inspector’ını tamamen özelleştirdik. EditorGUILayout sayesinde standart Unity kontrollerini kullanarak daha düzenli bir görünüm elde ettik.
Property Drawers: Alan Bazında Özelleştirme
Custom Inspector’lar tüm Component’i özelleştirirken, Property Drawers tek bir alanın (field) veya belirli bir veri tipinin Inspector’da nasıl çizileceğini özelleştirmek için kullanılır. Bu, özellikle projeniz genelinde sıkça kullandığınız özel veri tipleri veya nitelikler (Attributes) için idealdir.
Örneğin, bir float değişkenine belirli bir aralıkta değer atamak istediğinizde, bunun için özel bir [Range(min, max)] niteliği vardır. Ancak daha karmaşık bir görselleştirme (örneğin, iki kaydırıcılı bir min-max aralığı) istediğinizde kendi Property Drawer’ınızı yazmanız gerekir.
Temel adımlar:
- Özel Nitelik (Attribute) Oluşturma: Özelleştirmek istediğiniz alan için
PropertyAttributesınıfından türeyen bir nitelik oluşturun. - Property Drawer Sınıfı: Bu nitelik için
PropertyDrawersınıfından türeyen bir sınıf oluşturun. CustomPropertyDrawerNiteliği: Property Drawer sınıfınızın hangi niteliğe ait olduğunu belirtmek için[CustomPropertyDrawer(typeof(HedefNitelik))]kullanın.OnGUI()veGetPropertyHeight():OnGUI()metodu alanın nasıl çizileceğini tanımlarken,GetPropertyHeight()metodu alanın kaplayacağı yüksekliği belirler.
Property Drawer Örneği: Min-Max Aralık Kontrolü
Bir Vector2 kullanarak bir min-max aralığı tutan ve bunu iki kaydırıcı ile Inspector’da gösteren bir Property Drawer oluşturalım.
Önce özel niteliğimizi tanımlayalım:
using UnityEngine;
public class MinMaxRangeAttribute : PropertyAttribute
{
public float minLimit;
public float maxLimit;
public MinMaxRangeAttribute(float min, float max)
{
minLimit = min;
maxLimit = max;
}
}
Şimdi bu nitelik için Property Drawer’ı yazalım:
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(MinMaxRangeAttribute))]
public class MinMaxRangeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// Nitelik bilgilerini al
MinMaxRangeAttribute range = (MinMaxRangeAttribute)attribute;
// Sadece Vector2 tipleri için çalışır
if (property.propertyType == SerializedPropertyType.Vector2)
{
// Etiketi çiz
position = EditorGUI.PrefixLabel(position, label);
// Kaydırıcı alanını ikiye böl
float sliderWidth = position.width / 2f - 2f;
Rect minRect = new Rect(position.x, position.y, sliderWidth, position.height);
Rect maxRect = new Rect(position.x + sliderWidth + 4f, position.y, sliderWidth, position.height);
// Mevcut değerleri al
Vector2 currentValue = property.vector2Value;
float minVal = currentValue.x;
float maxVal = currentValue.y;
// Kaydırıcıları çiz
EditorGUI.MinMaxSlider(position, ref minVal, ref maxVal, range.minLimit, range.maxLimit);
// Alanları çiz
minVal = EditorGUI.FloatField(minRect, minVal);
maxVal = EditorGUI.FloatField(maxRect, maxVal);
// Değerleri sınırlara göre ayarla
minVal = Mathf.Max(minVal, range.minLimit);
maxVal = Mathf.Min(maxVal, range.maxLimit);
minVal = Mathf.Min(minVal, maxVal);
// Yeni değerleri kaydet
property.vector2Value = new Vector2(minVal, maxVal);
} else {
// Eğer Vector2 değilse, varsayılan Inspector'ı çiz
EditorGUI.LabelField(position, label.text, "Sadece Vector2 ile kullanın.");
}
}
// Alanın yüksekliğini ayarlayabiliriz, ancak bu örnekte varsayılan yeterli.
// public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
// {
// return base.GetPropertyHeight(property, label);
// }
}
Şimdi bu niteliği bir Component’te nasıl kullanacağımıza bakalım:
using UnityEngine;
public class EnemySpawnSettings : MonoBehaviour
{
[MinMaxRange(0f, 100f)]
public Vector2 spawnHealthRange = new Vector2(20f, 50f);
[MinMaxRange(1f, 10f)]
public Vector2 spawnCountRange = new Vector2(3f, 7f);
}
Bu sayede, EnemySpawnSettings Component’ine sahip bir GameObject seçtiğinizde, spawnHealthRange ve spawnCountRange değişkenleri için iki kaydırıcılı özel bir arayüz göreceksiniz. Bu, geliştiricilerin doğru aralıkları daha kolay ve görsel bir şekilde ayarlamasını sağlar.
İpuçları ve En İyi Uygulamalar
- Performans:
OnInspectorGUI()her karede çağrıldığı için, bu metot içinde pahalı işlemlerden kaçının. Sadece gerekli çizim kodunu içerdiğinden emin olun. - Hata Ayıklama: Editör script’lerinde hata ayıklama, normal oyun script’lerinden biraz farklı olabilir. Unity Editor’ı bir debugger’a bağlayarak breakpoint’ler kullanabilirsiniz.
- Kullanılabilirlik: Editörünüzü tasarlarken son kullanıcıyı (diğer geliştiriciler, tasarımcılar) düşünün. Ne kadar sezgisel olursa, o kadar faydalı olur.
- Geri Alma/Yineleme (Undo/Redo):
SerializedObjectveSerializedPropertykullanmak, Unity’nin yerleşik geri alma/yineleme sistemini otomatik olarak destekler. Kendi özel kontrollerinizi çizerkenEditorGUI.BeginChangeCheck()veEditorGUI.EndChangeCheck()kullanarak değişiklikleri algılayıp manuel olarak geri alma kaydı oluşturabilirsiniz. - Versiyon Kontrolü: Editör script’lerini diğer kodlarınızla birlikte versiyon kontrol sisteminize (Git, SVN vb.) eklemeyi unutmayın.
Sonuç
Unity’de Custom Inspector ve Property Drawers, oyun geliştirme sürecinizi kişiselleştirmenin ve optimize etmenin güçlü yollarıdır. Bu araçları kullanarak, karmaşık sistemleri daha yönetilebilir hale getirebilir, hata olasılığını azaltabilir ve ekip üyelerinizin verimliliğini artırabilirsiniz. Editörünüzü kendi ihtiyaçlarınıza göre şekillendirerek, sadece daha iyi oyunlar yapmakla kalmayacak, aynı zamanda geliştirme deneyiminizi de çok daha keyifli hale getireceksiniz. Şimdi kendi özel Inspector’larınızı ve Property Drawer’larınızı oluşturmaya başlayarak Unity’deki potansiyelinizi tam olarak keşfetme zamanı!



