Unity CustomEditor: Gelişmiş Inspector Arayüzleri Oluşturma
Unity CustomEditor: Gelişmiş Inspector Arayüzleri Oluşturma
Unity'de oyun geliştirirken, Inspector penceresi component'lerinizin (bileşenlerinizin) özelliklerini düzenlemek için kullandığınız ana araçtır. Ancak bazen varsayılan Inspector arayüzü, karmaşık bileşenleriniz veya özel araçlarınız için yeterince esnek veya kullanıcı dostu olmayabilir. İşte tam da bu noktada Unity CustomEditor devreye girer. Bu makalede,
CustomEditor attribute'unu kullanarak nasıl özel Inspector arayüzleri oluşturacağınızı, oyun geliştirme sürecinizi nasıl hızlandıracağınızı ve ekibiniz için daha güçlü araçlar sunacağınızı detaylıca inceleyeceğiz.Neden Unity CustomEditor Kullanmalıyız?
Varsayılan Inspector, çoğu durumda işinizi görür. Public (genel) değişkenlerinizi, serialize edilmiş private (özel) değişkenlerinizi veya
[SerializeField] attribute'u ile işaretlenmiş alanlarınızı otomatik olarak görüntüler ve düzenlemenize olanak tanır. Ancak, bazı senaryolarda bu yeterli değildir:- Karmaşık Veri Yapıları: Bir liste içinde özel bir sınıfınız varsa ve bu sınıfın elemanlarını daha görsel veya interaktif bir şekilde düzenlemek isterseniz.
- Kullanıcı Dostu Arayüzler: Oyun tasarımcılarının veya diğer geliştiricilerin bir bileşenin karmaşık ayarlarını daha kolay anlamasını ve değiştirmesini sağlamak için özel butonlar, kaydırıcılar veya grafiksel geri bildirimler eklemek.
- İş Akışını Hızlandırma: Tekrarlayan görevleri otomatikleştiren veya belirli bir bileşenle ilgili özel işlemleri tetikleyen butonlar eklemek.
- Görsel Geri Bildirim: Bir bileşenin durumunu (örneğin, bir AI'ın hedefi veya bir yol çizim aracı) Scene görünümünde veya Inspector'da görsel olarak belirtmek.
Unity CustomEditor, bu gibi ihtiyaçları karşılamak için tasarlanmıştır ve geliştiricilere kendi Inspector görünümlerini tam kontrol etme gücü verir.
CustomEditor Temelleri: İlk Adımlar
Bir Unity CustomEditor oluşturmak oldukça basittir. Temel olarak, düzenlemek istediğiniz
MonoBehaviour veya ScriptableObject sınıfı için özel bir Editor sınıfı yazarsınız.Editor Klasörü ve Sınıf Yapısı
Unity, Editor script'lerini özel bir şekilde ele alır. Bu script'ler sadece Unity Editor'ünde çalışır ve derlenmiş oyununuza dahil edilmez. Bu nedenle, tüm Editor script'lerinizi projenizin herhangi bir yerindeki "Editor" adında bir klasörün içine yerleştirmeniz zorunludur. Örneğin, "Assets/Scripts/Editor" veya "Assets/MyFeature/Editor" gibi.
İşte basit bir CustomEditor sınıfının yapısı:
using UnityEditor;
using UnityEngine;// Düzenlemek istediğimiz MonoBehaviour sınıfı
public class MyCustomComponent : MonoBehaviour
{
public int myIntValue;
public string myStringValue;
public bool myBoolValue;
public void DoSomethingComplex()
{
Debug.Log("Karmaşık bir işlem yapıldı!");
}
}
// MyCustomComponent için özel Editor
[CustomEditor(typeof(MyCustomComponent))]
public class MyCustomComponentEditor : Editor
{
// Inspector'da çizilecek ana metod
public override void OnInspectorGUI()
{
// Hedef component'e referans
MyCustomComponent myComponent = (MyCustomComponent)target;
// Değişiklikleri izlemeye başla
// Bu, Inspector'da yapılan değişikliklerin Undo sistemine kaydedilmesi için önemlidir.
// Ayrıca, GUI.changed true ise ApplyModifiedProperties'in çağrılmasını sağlar.
serializedObject.Update();
// Varsayılan Inspector'ı çizmek isterseniz:
// DrawDefaultInspector();
// Kendi özel UI elemanlarımızı çizelim:
EditorGUILayout.LabelField("Bu benim özel başlığım!");
// Serialize edilmiş özellikleri PropertyField ile çizmek
// Bu, Undo/Redo ve prefab override desteği sağlar.
EditorGUILayout.PropertyField(serializedObject.FindProperty("myIntValue"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("myStringValue"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("myBoolValue"));
// Özel bir buton ekleyelim
if (GUILayout.Button("Karmaşık İşlemi Yap"))
{
myComponent.DoSomethingComplex();
}
// Yapılan değişiklikleri serialize edilmiş objeye uygula
// Bu, Inspector'daki değişikliklerin component'e kaydedilmesini sağlar.
serializedObject.ApplyModifiedProperties();
}
}
OnInspectorGUI() Metodu
Editor sınıfından türettiğiniz her özel Editor'ün ana kalbi OnInspectorGUI() metodudur. Bu metod, Inspector penceresi her yeniden çizildiğinde çağrılır. Bu metodun içinde, EditorGUILayout ve EditorGUI sınıflarını kullanarak çeşitli UI elemanlarını (butonlar, kaydırıcılar, metin alanları vb.) çizersiniz.Inspector'ı Özelleştirme: SerializedObject ve EditorGUILayout
Unity Editor'ünde bir bileşenin özelliklerini manipüle etmenin en güvenli ve önerilen yolu
SerializedObject ve SerializedProperty kullanmaktır. Doğrudan target objesinin alanlarını değiştirmek, Undo (geri al) sistemiyle sorunlara yol açabilir ve prefab override sistemini bozabilir.SerializedObject ve SerializedProperty
serializedObject, Editor sınıfının bir özelliğidir ve düzenlemekte olduğunuz hedef objenin (target) serialize edilmiş halini temsil eder. Bu obje üzerinden FindProperty() metodunu kullanarak herhangi bir public veya [SerializeField] ile işaretlenmiş değişkene SerializedProperty olarak erişebilirsiniz.// myIntValue adında bir SerializedProperty bul
SerializedProperty intProp = serializedObject.FindProperty("myIntValue");// Bu property'yi Inspector'da çiz
EditorGUILayout.PropertyField(intProp);
// Veya değerini doğrudan değiştirmek isterseniz (genellikle kaçınılmalıdır, PropertyField tercih edilir):
// intProp.intValue = EditorGUILayout.IntField("My Int Value", intProp.intValue);
EditorGUILayout Kullanımı
EditorGUILayout sınıfı, Inspector'da UI elemanları çizmek için kullanılan statik metodlar içerir. Bu metodlar, otomatik olarak layout (düzenleme) yapar ve genellikle EditorGUI sınıfına göre daha kolay kullanılır. Örneğin, bir metin alanı, bir buton veya bir kaydırıcı ekleyebilirsiniz.// Bir metin alanı
myComponent.myStringValue = EditorGUILayout.TextField("My String", myComponent.myStringValue);// Bir boolean toggle
myComponent.myBoolValue = EditorGUILayout.Toggle("My Boolean", myComponent.myBoolValue);
// Bir kaydırıcı (slider)
myComponent.myIntValue = EditorGUILayout.IntSlider("My Int Slider", myComponent.myIntValue, 0, 100);
Unutmayın,
EditorGUILayout ile doğrudan target objesinin alanlarını değiştirirken, değişikliklerin Unity tarafından algılanması ve kaydedilmesi için EditorUtility.SetDirty(target) ve Undo sistemi için Undo.RecordObject(target, "Değişiklik Adı") kullanmanız gerekir. SerializedObject sistemi bu işlemleri otomatik olarak halleder, bu yüzden genellikle tercih edilen yöntemdir.Pratik İpuçları ve En İyi Uygulamalar
1. Varsayılan Inspector'ı Korumak
Bazen sadece birkaç alanı özelleştirmek, geri kalanını Unity'nin otomatik olarak çizmesini istersiniz. Bunun için
DrawDefaultInspector() metodunu kullanabilirsiniz:public override void OnInspectorGUI()
{
DrawDefaultInspector(); // Tüm varsayılan alanları çizerMyCustomComponent myComponent = (MyCustomComponent)target;
// Sadece özel butonumuzu ekleyelim
if (GUILayout.Button("Özel İşlem Yap"))
{
myComponent.DoSomethingComplex();
}
}
Bu, mevcut bir Unity CustomEditor'ı genişletmek veya sadece küçük bir ekleme yapmak istediğinizde çok kullanışlıdır.
2. Değişiklikleri Kaydetmek ve Geri Almak (Undo)
SerializedObject kullanırken, serializedObject.Update() ile değişiklikleri izlemeye başlar ve serializedObject.ApplyModifiedProperties() ile değişiklikleri objeye uygularsınız. Bu, otomatik olarak Undo/Redo sistemini ve prefab override'larını destekler. Eğer target objesinin alanlarını doğrudan manipüle ediyorsanız, bu adımları manuel olarak yapmanız gerekir:public override void OnInspectorGUI()
{
MyCustomComponent myComponent = (MyCustomComponent)target;// Değişiklikleri geri alabilmek için objeyi kaydet
Undo.RecordObject(myComponent, "My Custom Component Değişikliği");
// Bir değeri değiştir
int newIntValue = EditorGUILayout.IntField("My Int Value", myComponent.myIntValue);
if (newIntValue != myComponent.myIntValue)
{
myComponent.myIntValue = newIntValue;
// Objenin değiştiğini Unity'ye bildir, böylece kaydedilir
EditorUtility.SetDirty(myComponent);
}
}
Her zaman
SerializedObject kullanmak en güvenli ve önerilen yöntemdir, çünkü bu karmaşıklığı sizin için yönetir.3. [HideInInspector] ile Karışıklığı Önlemek
Eğer bir alanı kendi Unity CustomEditor'ınızda özel olarak çiziyorsanız, varsayılan Inspector'ın bu alanı tekrar çizmesini engellemek için ilgili değişkene
[HideInInspector] attribute'unu ekleyebilirsiniz. Bu, Inspector'da çifte alan görünümünü engeller ve daha temiz bir arayüz sağlar.public class MyCustomComponent : MonoBehaviour
{
[HideInInspector] // Bu alan varsayılan Inspector'da görünmez
public int myIntValue;
public string myStringValue;
}
4. Çoklu Obje Düzenleme
CustomEditor'lar otomatik olarak birden fazla objeyi aynı anda düzenlemeyi destekler. target özelliği, seçilen ilk objeyi döndürürken, targets özelliği seçilen tüm objelerin bir dizisini döndürür. SerializedObject ile çalışırken, bu durum otomatik olarak yönetilir ve yaptığınız değişiklikler seçili tüm objelere uygulanır. Eğer özel bir mantıkla her bir objeyi ayrı ayrı manipüle etmek isterseniz, targets dizisini kullanabilirsiniz.Yaygın Hatalar ve Çözümleri
1. Editor Script'lerinin Konumu
Hata: Editor script'i çalışmıyor veya derleme hatası veriyor.
Çözüm: Tüm Editor script'lerinizin (CustomEditor sınıfları dahil) projenizin "Editor" adında bir klasörün içinde olduğundan emin olun. Bu klasörün adı büyük/küçük harf duyarlıdır.
2. ApplyModifiedProperties() Çağrısını Unutmak
Hata: Inspector'da yaptığım değişiklikler kaydedilmiyor veya oyun çalıştırıldığında sıfırlanıyor.
Çözüm: OnInspectorGUI() metodunun sonunda serializedObject.ApplyModifiedProperties() metodunu çağırdığınızdan emin olun. Bu metod, serializedObject.Update()'ten bu yana yapılan tüm değişiklikleri gerçek objeye uygular.
3. target Tip Dönüşüm Hataları
Hata:
target objesini kendi component tipime dönüştürürken hata alıyorum veya null referans hatası yaşıyorum.Çözüm: [CustomEditor(typeof(MyComponent))] attribute'undaki tip ile target'ı dönüştürmeye çalıştığınız tipin eşleştiğinden emin olun. Ayrıca, Editor'ınızın doğru bir component'i hedeflediğinden emin olun. Genellikle (MyComponent)target; güvenli bir dönüşümdür, çünkü CustomEditor attribute'u zaten doğru tipi garanti eder.
Performans ve Optimizasyon Notları
OnInspectorGUI() metodu her frame'de veya Inspector penceresi her güncellendiğinde çağrılabilir. Bu nedenle, bu metodun içinde ağır performanslı işlemlerden kaçınmak önemlidir. Özellikle şunlara dikkat edin:- Ağır Hesaplamalar: Karmaşık matematiksel işlemler, dosya okuma/yazma veya ağ istekleri gibi yoğun işlemleri
OnInspectorGUI()içinde yapmaktan kaçının. Bu tür işlemleri, Editor'ınızınOnEnable()veya bir buton tıklaması gibi olaylar üzerine tetikleyin. - Gereksiz Çizim: Sadece değişen veya etkileşime girilen UI elemanlarını yeniden çizmek için koşullu mantık kullanın. Ancak
EditorGUILayoutveSerializedObjectçoğu durumda bu optimizasyonu sizin için zaten yapar. - AssetDatabase İşlemleri: Eğer Editor'ınız
AssetDatabaseile etkileşime giriyorsa (örneğin asset oluşturma, silme), bu işlemleri genellikle bir buton tıklaması gibi kullanıcı etkileşimi üzerine veyaOnEnablemetodunda yapın.
Unity CustomEditor, Unity geliştiricileri için inanılmaz derecede güçlü bir araçtır. Kendi özel Inspector'larınızı oluşturarak, bileşenlerinizin kullanımını basitleştirebilir, iş akışınızı hızlandırabilir ve genel geliştirme deneyimini önemli ölçüde iyileştirebilirsiniz. Bu makaledeki bilgilerle, artık kendi özel Editor'lerinizi oluşturmaya hazırsınız. Deneyler yapmaktan ve yaratıcı çözümler üretmekten çekinmeyin!
🧠 Ders Sonu Değerlendirme Testi
Dersi tamamladıktan sonra bilgilerinizi test edin ve ekstra puanlar kazanın.
Yorumlar (0)
İlk yorumu siz yapın!