Hepinize merhabalar,
Bu derste Unity 3D için basit editör scriptleri yazmayı göreceğiz. Unity’i editör scriptleri ile daha da işlevselleştirmek bazen karmaşık projelerinizde işinizi oldukça rahatlatabilir.
Editör scripti yazmak için Unity’nin gerçekten çok fazla fonksiyonu mevcut ve bunların hepsini ele almak benim için mümkün değil. Ben sıklıkla kullanılan fonksiyonlardan ve attribute‘lardan bahsetmeye çalışacağım. Bu derste OnInspectorGUI fonksiyonu ile ContextMenu ve MenuItem attribute’larını göreceğiz. Dersi C# ile anlatacağım ve bir miktar kod yazma bilginiz olduğunu varsayacağım.
Hazırsanız başlayalım…
Editör scriptleriyle çalışırken bu scriptleri projenizde Editor isminde bir klasöre kaydetmeniz gerekmekte. Bu yüzden Project panelinde Editor isminde bir klasör oluşturun. Ardından bu klasör içerisinde “EditorScript1” adında yeni bir C# scripti oluşturup içeriğini şöyle değiştirin:
using UnityEngine; using UnityEditor; public class EditorScript1 : Editor { // Kısayol: Yok [MenuItem( "CONTEXT/Transform/Yukari Git" )] static void TransformYukariTasi( MenuCommand mc ) { // Yukari Git komutunun çalıştırıldığı Transform'u değişkene kaydet Transform tr = (Transform) mc.context; // Transform'u ellemeden önce Undo desteği sağla Undo.RecordObject( tr, "Yukari Git" ); // Transform'u 1 birim yukarı taşı tr.position += new Vector3( 0f, 1f, 0f ); } // Kısayol: Control + G [MenuItem( "GameObject/Buyuk Kup Olustur %g", false, 10 )] static void BuyukKupYap( MenuCommand mc ) { // Yeni bir küp oluştur GameObject go = GameObject.CreatePrimitive( PrimitiveType.Cube ); // Eğer bir obje seçili ise küpü o objenin child'ı yap GameObjectUtility.SetParentAndAlign( go, (GameObject) mc.context ); // Küpü büyüt go.transform.localScale = new Vector3( 5f, 5f, 5f ); // Küp oluşturma işlemini Undo yapabilmeyi sağla Undo.RegisterCreatedObjectUndo( go, "Buyuk Kup Olustur" ); // Yeni oluşan küpü seçili hale getir Selection.activeObject = go; } // Kısayol: H [MenuItem( "Benim Menum/Secili Objeleri Yukari Tasi _h" )] static void IsimsizFonksiyon() { // Hierarchy'deki seçili objelerin listesini al Transform[] seciliObjeler = Selection.transforms; // Eğer en az bir obje seçili ise if( seciliObjeler.Length > 0 ) { // (Olası) birden çok obje için Undo desteği sağla Undo.RecordObjects( seciliObjeler, "Secili Objeleri Ziplat" ); // Seçili objeleri 1 birim yukarı taşı for( int i = 0; i < seciliObjeler.Length; i++ ) { seciliObjeler[i].position += new Vector3( 0f, 1f, 0f ); } } } }
Bu kod üç farklı işe yarıyor:
- Transform component’ine “Yukari Git” adında bir komut ekliyor. Bu komuta, herhangi bir objeyi seçip Transform’unun sağ üstündeki dişli çarka tıklayarak erişebilirsiniz. Eğer “Yukari Git” seçeneğini seçerseniz obje 1 birim yukarı ışınlanıyor.
- Unity’nin üstteki araç çubuğundaki GameObject menüsüne “Buyuk Kup Olustur” adında bir buton ekliyor ve bu butona tıklayınca sahnede 5x5x5 ebatlarında bir küp oluşturuyor. Ayrıca CTRL+G kısayolu ile de bu fonksiyon çağrılabiliyor.
- Yukarıdaki araç çubuğuna “Benim Menum” adında bir sekme ekliyor ve bunun içerisine “Secili Objeleri Yukari Tasi” adında bir buton koyuyor. Bu butona tıklayınca sahnedeki seçili tüm objeler 1 birim yukarı taşınıyor. Bu fonksiyon H kısayolu ile de çağrılabiliyor.
Peki bu işlevselliği Unity’e nasıl kazandırdık? Öncelikle scriptimizin MonoBehaviour class’ı yerine Editor class’ını extend etmesini sağladık: “public class EditorScript1 : Editor”. Eğer Javascript kullanıyor olsaydık da orası “public class EditorScript1 extends Editor” olacaktı. Editor class’ı UnityEditor package‘ında olduğu için o package’ı “using UnityEditor;” komutuyla import ediyoruz (Javascript’te buna gerek yok).
Unity’de bir fonksiyonu araç çubuğundan çağırabilmek için MenuItem attribute‘ü kullanılır. Bu attribute parametre olarak fonksiyonu çağırmaya yarayan butona giden yolu (bir string olarak) alır. Örneğin IsimsizFonksiyon isimli üçüncü fonksiyonumuzun başına koyduğumuz MenuItem’a parametre olarak “Benim Menum/Secili Objeleri Yukari Tasi _h” verdik ve bu sayede bu fonksiyonu araç çubuğundan Benim Menum-Secili Objeleri Yukari Tasi yolunu izleyerek çağırabiliyoruz.
NOT: C#‘ta MenuItem’ı [ ve ] işaretleri arasına sararken Javascript‘te attribute’ın başına bir tane @ koymamız yetiyor.
String’in en sonundaki “_h” kısmı, bu butona bir kısayol tuşu atayabilmemize yarıyor. Bu kısayol tuşunu belirlemeden önce bir karakter boşluk bırakıyoruz. Kısayol tuşumuz CTRL tuşunu içersin istiyorsak % işareti, Shift tuşunu içersin istiyorsak # işareti, Alt tuşunu içersin istiyorsak da & işareti kullanıyoruz. Örneğin ikinci fonksiyon olan BuyukKupYap fonksiyonunun kısayolu “%g“, yani CTRL+G. Bu kısayolun CTRL+ALT+G olmasını isteseydik kısayol olarak “%&g” yazacaktık. Eğer CTRL, Alt veya Shift tuşlarından hiçbiri kısayolda yoksa o zaman kısayol tuşunun başına _ işareti koyuyoruz. Örneğin kısayolumuz “_g” olsaydı bu durumda sadece G tuşuna basınca o fonksiyon çalışırdı.
İsterseniz ilk fonksiyondan başlayarak kodu daha detaylı inceleyelim. TransformYukariTasi isimli ilk fonksiyonumuzun MenuItem attribute’u parametre olarak “CONTEXT/Transform/Yukari Git” almış. Burada özel bir durum söz konusu. Eğer Inspector‘dan belli bir component’in sağ üstündeki dişli ikona tıklayınca orada kendi yazdığımız bir seçeneğin gözükmesini istiyorsak o zaman en başa “CONTEXT” yazıyoruz, ardından hangi component’e buton koyacağımızı yazıyoruz (Transform) ve son olarak butonun ismini giriyoruz (Yukari Git).
MenuItem ile çağırdığımız fonksiyonlar static olmak zorunda. Bu static fonksiyona istersek MenuCommand türünde bir parametre verebiliyoruz. CONTEXT ile çalışıyorsak MenuCommand parametresine, hangi component’in dişli ikonunu kullanarak o fonksiyonu çağırdıysak o component değer olarak veriliyor. Örneğin Main Camera‘nın Transform‘undaki dişliye tıklayıp “Yukari Git” seçeneğini seçersek MenuCommand’e değer olarak Main Camera objesinin Transform component’i gider. MenuCommand’den bu Transform’a erişmek için MenuCommand’in context değişkenini Transform’a typecast yapıyoruz (ilk satırda). Editör scriptiyle çalışırken yaptığınız değişiklikler normalde Undo-Redo desteklemez, bu özelliği sizin elle sağlamanız lazım. Bunun içindir ki bir sonraki satırda “Undo.RecordObject( tr, “Yukari Git” );” fonksiyonunu çağırıyoruz. Bir obje üzerinde yapacağımız değişikliğin Undo desteklemesini istiyorsak değişiklik yapmadan önce Undo.RecordObject fonksiyonunu çağırıp ilk parametreye objeyi veriyoruz. İkinci parametreye ise yaptığımız değişikliğin ufacık bir açıklamasını giriyoruz (bu açıklama Edit-Undo seçeneğinin yanında gösteriliyor). Artık Undo desteklediğimize göre son satırda transform‘un y pozisyonunu 1 birim artırarak fonksiyonu sonlandırıyoruz.
TransformYukariTasi’yı test etmek için kameraya “Yukari Git” işlemi uygulayın ardından “Edit-Undo Yukari Git” (veya CTRL+Z) ile bu işlemi geri alabildiğinizi teyit edin.
Gelelim ikinci fonksiyona. Bu fonksiyonu çağırmaya yarayan butonun GameObject menüsü altında gözükmesini istiyoruz. Unity dökümanında yazdığına göre eğer GameObject menüsüne bir buton koyacaksak o zaman o MenuItem‘ın sonuna false ve 10 şeklinde iki parametre daha eklememiz gerekiyormuş. Bende bu sebepten ötürü ikinci fonksiyonun MenuItem attribute’unun sonuna bu iki parametreyi veriyorum. Bu fonksiyonun kısayolu “%g“, yani CTRL+G.
Fonksiyonun içinde öncelikle GameObject.CreatePrimitive fonksiyonu ile sıradan bir küp oluşturuyoruz. Sonraki satırda yaptığımız şey ise şu: eğer Hierarchy‘de bir objeye sağ tıklarsak GameObject menüsünün bir kopyası orada da gözüküyor ve bu yolla bir obje oluşturursak oluşturulan obje, seçtiğimiz objenin otomatik olarak bir child‘ı oluyor. Örneğin Hierarchy’den Main Camera’ya sağ tıklayıp menüden “Buyuk Kup Olustur“u seçin (bu durumda oluşan 5x5x5’lik küp otomatik olarak Main Camera’nın bir child’ı olacak):
Bu otomatik olarak child’ı olma olayını işte ikinci satırda yapıyoruz. Eğer Hierarchy’de bir objeye sağ tıklayıp “Buyuk Kup Olustur” demişsek, üzerine sağ tıkladığımız obje MenuCommand parametresine değer olarak veriliyor. GameObjectUtility.SetParentAndAlign isimli fonksiyon ise bu parent etme olayını (ve belki başka bir takım şeyleri daha) ayarlayıp bizim işimizi kolaylaştırıyor. Üçüncü satırda localScale ile küpün boyutunu 5x5x5 yaparken 4. satırda ise Undo.RegisterCreatedObjectUndo fonksiyonu ile bu yeni oluşturduğumuz küpün Undo yaparsak yok edilebilmesini sağlıyoruz. Az önce Undo.RecordObject yaparken niye şimdi farklı bir Undo fonksiyonu kullandık diyebilirsiniz haklı olarak. Şöyle ki, Unity editöründe bazı özel operasyonların Undo fonksiyonu da farklı oluyor. Yeni bir obje oluşturduysak bunun Undo desteklemesi için RegisterCreatedObjectUndo kullanmak zorundayız. Hangi durumda hangi Undo’yu kullanacağınızı öğrenmenin en iyi yolu Unity Script Reference‘de Undo sayfasına erişip oradaki açıklamaları okumak. Fonksiyonun en sonunda “Selection.activeObject = go;” yapıyoruz. Bu komutun tek yaptığı şey “go” değişkeninde tutulan GameObject‘i otomatik olarak seçili hale getirmek. Böylece yeni bir büyük küp oluşturunca o oluşan küp otomatik olarak seçili hale geliyor.
Sanırım artık IsimsizFonksiyon isimli üçüncü fonksiyonu inceleyebiliriz. Kısayol “_h“, yani sadece H tuşu. İlk satırda Selection.transforms ile Hierarchy‘deki seçili objelerin Transform component’lerini bir Transform array‘ine atıyoruz (çünkü bu fonksiyon seçili olan tüm Transform’ları etkileyecek). Eğer en az 1 obje seçili ise, seçtiğimiz (olası) birden fazla obje üzerinde yapacağımız değişikliklerin topluca Undo desteklemesi için Undo.RecordObjects fonksiyonunu kullanıyoruz ve ardından seçimdeki tüm Transform’ları y ekseninde 1 birim yukarı taşıyoruz. İşte bu kadar basit!
Şimdi daha basit bir script ile yolumuza devam edelim. Project panelinde Editor klasörünün dışında istediğiniz bir yerde “ContextMenuTest” isminde yeni bir C# script oluşturun. Bu scriptin Editor klasörü içerisinde olmasına gerek yok çünkü kendisi gerçekte bir Editor scripti değil. Scriptin içeriğini şu şekilde güncelleyin:
using UnityEngine; public class ContextMenuTest : MonoBehaviour { public int sayi = 1; public float sayi2 = 1.11f; [ContextMenu( "Degerleri Ikiye Katla" )] void DegerleriKatla() { sayi = sayi * 2; sayi2 = sayi2 * 2; } }
Gördüğünüz üzere bu script ne UnityEditor‘ü import ediyor ne de Editor class’ını extend ediyor. Yani scriptin normalde yazdığımız scriptlerden hiçbir farkı yok. Scriptte iki tane değişken var ve bir de DegerleriKatla isminde basit bir fonksiyon. Bu fonksiyonun tek yaptığı değişkenleri 2 ile çarpmak. Burada dikkatinizi çeken tek şey ContextMenu attribute‘ü olsa gerek. Bu attribute de parametre olarak bir string alıyor. Kamera objesine ContextMenuTest’i component olarak eklersek ve Inspector‘da component’in sağ üstündeki dişli çarka tıklarsak bu isme sahip bir buton karşımıza geliyor:
CONTEXT parametresine sahip MenuItem attribute’ü de aynı şeyi yapıyordu diyebilirsiniz. Aradaki fark şu ki CONTEXT’li MenuItem ile istediğimiz component’e bir buton ekleyebiliyoruz ancak Editor class’ını extend etmemiz gerekiyor. ContextMenu’de ise buton sadece o component’e etki ediyor ve Editor class’ını extend etmemiz de gerekmiyor. Eğer “Degerleri Ikiye Katla” butonuna basarsanız Inspector’da iki değişkeninde ikiye katlandığını görebilirsiniz.
Bu ufacık scripti de hallettiğimize göre geriye son scriptimiz kaldı. Editor klasörü içerisinde “EditorScript2” adında yeni bir C# script oluşturup içeriğini değiştirin:
using UnityEngine; using UnityEditor; // Bu editör scripti, ContextMenuTest scriptini düzenlemeye yarayacak [CustomEditor( typeof( ContextMenuTest ) )] public class EditorScript2 : Editor { // ContextMenuTest component'inin Inspector'dakini görünümünü kişiselleştir public override void OnInspectorGUI() { // Seçili objedeki ContextMenuTest component'ine eriş ContextMenuTest scr = (ContextMenuTest) target; // Inspector'a basit bir mesaj kutusu çizdir EditorGUILayout.HelpBox( "Inspector'un Normal Hali", MessageType.Info ); // Unity'e bu component'in Inspector'unu kendi bildiği yoldan çizmesini söyle DrawDefaultInspector(); // Basit bir mesaj kutusu daha çizdir EditorGUILayout.HelpBox( "Inspector'un Degistirilmis Hali", MessageType.Info ); // Component'teki sayi değişkeninin değerini değiştirmeye yarayan bir field ekle scr.sayi = EditorGUILayout.IntField( "Sayi:", scr.sayi ); // **sayi'yı değiştirirmenin bir başka yolu** // // GUILayout.EndHorizontal görene kadarki tüm içeriği tek bir satıra sığdırmaya çalış GUILayout.BeginHorizontal(); // Inspector'a "Sayi: " şeklinde bir yazı (label) yazdır GUILayout.Label( "Sayi: " ); // Inspector'a bir - butonu çizdir ve butona basılırsa sayi'yı 10'a böl if( GUILayout.Button( "-" ) ) scr.sayi = scr.sayi / 10; // sayi değişkeninin değerini değiştirmeye yarayan bir field ekle // (bu sefer string parametresi vermedik) scr.sayi = EditorGUILayout.IntField( scr.sayi ); // Inspector'a bir + butonu çizdir ve butona basılırsa sayi'yı 10'la çarp if( GUILayout.Button( "+" ) ) scr.sayi = scr.sayi * 10; // Tek satıra sığdırma işlemini bitir GUILayout.EndHorizontal(); // **** // // sayi2 değişkeninin değerini bir slider ile değiştirmeyi sağla (min:0, max: 250) scr.sayi2 = EditorGUILayout.Slider( "Sayi2:", scr.sayi2, 0f, 250f ); // Eğer sayi değişkeni 75'ten büyükse Inspector'a bir mesaj kutusu çizdir if( scr.sayi > 75 ) EditorGUILayout.HelpBox( "Sayi epey büyük!", MessageType.Warning ); // Inspector'a bir buton çizdir (GUILayout da işe yarıyor) // Butona basılırsa Degerleri3IleCarp fonksiyonunu çağır if( GUILayout.Button( "Degerleri 3'le Carp" ) ) Degerleri3IleCarp(); } // ContextMenuTest component'indeki değerleri 3 ile çarp void Degerleri3IleCarp() { // Seçili objedeki ContextMenuTest component'ine eriş ContextMenuTest scr = (ContextMenuTest) target; // Değişkenleri 3 ile çarp scr.sayi = scr.sayi * 3; scr.sayi2 = scr.sayi2 * 3; // Kendi yazdığımız bir scriptteki değerleri bir editör scriptinden // elle değiştirince, bu değerlerin düzgünce kaydedildiğinden // emin olmak için EditorUtility.SetDirty fonksiyonundan faydalan EditorUtility.SetDirty( scr ); } // Kısayol: CTRL + Shift + G [MenuItem( "Benim Menum/Secili Objeye ContextMenuTest Ekle %#g" )] static void ComponentEkle() { // Eğer bir obje seçili ise if( Selection.activeTransform != null ) { // Seçili objeye ContextMenuTest component'i ekle ve bu işlemin Undo desteklemesini sağla Undo.AddComponent<ContextMenuTest>( Selection.activeTransform.gameObject ); } } }
Bu script de ilk script gibi Editor class’ını extend ediyor ve UnityEditor package’ını kullanıyor. Gözünüze ilk çarpan şey muhtemelen CustomEditor attribute‘üdür. Eğer bir component’in Inspector‘daki görünümünü değiştirmek istiyorsak onun için bir editör scripti yazmalı ve onun OnInspectorGUI fonksiyonunu değiştirmeliyiz. Buradaki “onun için bir editör scripti yazma” olayı CustomEditor ile oluyor. Bu attribute ile bu editör scriptinin belli bir component’i etkilemesini sağlayabiliyoruz. Bizim durumumuzda bu ContextMenuTest component’i oluyor. Artık bu script içerisinde OnInspectorGUI fonksiyonu oluşturursak bu fonksiyon içerisinde yazdığımız arayüz kodu direkt olarak ContextMenuTest component’inin Inspector’daki görünümünü etkileyecek. Biz de öyle yapıyoruz ve scriptin en başına bir OnInspectorGUI fonksiyonu koyuyoruz. Bu fonksiyonun başına özellikle bir “override” keyword’ü koymak zorundayız.
Fonksiyonun en başında, üzerinde çalıştığımız ContextMenuTest component’ini scr isimli bir değişkene atıyoruz: “ContextMenuTest scr = (ContextMenuTest) target;“. Buradaki target değişkeni havadan gelmiş gibi durabilir ama aslında bu değişken, extend ettiğimiz Editor class‘ından geliyor (eğer Editor’u Unity Script Reference’dan araştırırsanız bir takım faydalı örnek kodlar da bulabilirsiniz).
OnInspectorGUI ile arayüz çizdirmek için karşımızda iki seçenek var: GUILayout veya EditorGUILayout. Eski Unity sürümlerinde GUI ve GUILayout class’larını kullanarak kod vasıtasıyla arayüz oluşturuyorduk, o sürümleri kullananlarınız GUILayout’a biraz aşina olabilir. GUILayout ile kabataslak bir şekilde yazılar, butonlar, slider’lar vb. oluşturabiliyorduk. Aynı şeyi burada da yapabiliyoruz. Ancak editör scriptlerinde arayüz oluştururken öncelikle aradığınız fonksiyonun EditorGUILayout’ta bir karşılığı var mı diye araştırın, eğer yoksa o zaman GUILayout’a geçiş yapın. Zira adından da anlaşılacağı üzere EditorGUILayout class’ı özellikle editör için arayüz oluşturmak için yazılmış bir class. Unity Script Reference‘den bakarsanız bu class’ın içinde yer alan pek çok hazır fonksiyonu da görebilirsiniz ve emin olun bu fonksiyonlar basit arayüzlerde işinizi görmeye yetiyor.
Editör ekranında GUILayout veya EditorGUILayout kullanırsanız oluşturduğunuz içerik yukarıdan aşağıya doğru çizdirilir. OnInspectorGUI‘de öncelikle EditorGUILayout.HelpBox ile basit bir kutucuğun içerisine “Inspector’un Normal Hali” yazısı yazdırıyoruz. İkinci parametre olan MessageType sadece bu kutucuğun yanında yer alacak olan ikonu etkiliyor, yani önemli birşey değil. Kutucuğu çizdirdikten sonra DrawDefaultInspector() fonksiyonunu çağırıyoruz. Bu fonksiyon, Editor class’ı içerisinde halihazırda yazılmış olan kullanıma hazır bir fonksiyon. Bu fonksiyonu çağırdığımızda; ContextMenuTest için editör scripti yazmasaydık varsayılan olarak o component’in Inspector‘u nasıl çizilecek iseydi işte o varsayılan (default) çizimi editör scriptli haline de uygulayabiliyoruz. Bu fonksiyonu çağırmak zorunda değiliz; ben sadece göstermek istedim:
Biraz devam edince HelpBox ile yeni bir kutucuk daha çizdiriyoruz ve ardından şu kodu çalıştırıyoruz: “scr.sayi = EditorGUILayout.IntField( “Sayi:”, scr.sayi );“. Hatırlarsanız scr değişkenine, üzerinde çalıştığımız ContextMenuTest component‘ini değer olarak vermiştik. Burada yaptığımız şey ise o scriptteki sayi değişkeninin değerini değiştirebilmek için Inspector’da bir integer field‘ı çizdirmek. Bu field’ı kullanarak sayi değişkeninin değerini değiştirebiliriz:
Varsayılan olarak arayüz elemanları yukarıdan aşağı dizilir demiştim. Ancak bu spesifik örnek için ben arayüz elemanlarının bir kısmını soldan sağa dizmek istiyorum. Bu durumda GUILayout.BeginHorizontal() ile GUILayout.EndHorizontal() fonksiyonları arasına ne yazarsam, yazdığım bu arayüz elemanları soldan sağa dizilir. GUILayout kullanıyorum çünkü BeginHorizontal’ın EditorGUILayout’ta karşılığı yok. Yapmak istediğim şey şöyle birşey:
Öncelikle “Sayi:” şeklinde bir string bastırmak, sonra bir “–” butonu çizdirmek, sonra bir int field ve son olarak da bir “+” butonu çizdirmek. String’i yazdırmak için GUILayout.Label, int field’ı çizdirmek için ise yine EditorGUILayout.IntField kullanıyorum. Butonları ise GUILayout.Button ile çizdiriyorum. Eğer Button fonksiyonunu bir if‘in içine alırsanız, bu butona tıklayınca if koşulunun içindeki kod çalıştırılır. Ben de “-” butonuna basınca sayıyı 10’a bölüyor, “+” tuşuna basınca sayıyı 10 ile çarpıyorum. GUILayout.EndHorizontal() ile de arayüz elemanlarını yatay yerleştirmeye bir son veriyorum.
ContextMenuTest‘teki sayi2 float değişkeninin değerini değiştirmek için “scr.sayi2 = EditorGUILayout.Slider( “Sayi2:”, scr.sayi2, 0f, 250f );” kodunu kullanıyoruz. Bu kod ekrana bir slider çiziyor ve slider’ı 0 ile 250 sayıları arasında tutuyor. Bir sonraki satırda, eğlence amaçlı, eğer sayi değişkeni 75’ten büyükse bir başka mesaj kutucuğu daha çizdiriyorum:
Son olarak en alta bir buton daha çizdiriyorum ve butona basılırsa Degerleri3IleCarp fonksiyonunu çağırıyorum. Bu fonksiyonda ContextMenuTest component’inin değişkenlerini 3 ile çarpıyorum. Sonra ise “EditorUtility.SetDirty( scr );” fonksiyonunu çağırıyorum. Bu fonksiyonun tam olarak ne zaman kullanılması gerektiğini bilmiyorum ancak eğer Unity’nin kendi component’lerinden biriyle değil de kendi yazdığınız bir component ile (ContextMenuTest) uğraşıyorsanız ve bu component’in bir değişkenini bir EditorGUILayout fonksiyonu ile değil de direkt elle değiştiriyorsanız ( “scr.sayi = scr.sayi * 3;” ) bu değişikliğin Unity tarafından kaydedildiğini garanti altına almak için SetDirty fonksiyonunu çağırmak isteyebilirsiniz. Çünkü bu fonksiyon, içine parametre olarak girilen component’in değerlerinin düzgünce kaydedilmesini sağlıyor.
EditorScript2’nin en sonunda ComponentEkle isimli static bir fonksiyon var ve MenuItem attribute’ü ile bu fonksiyonu “Benim Menum/Secili Objeye ContextMenuTest Ekle” yolunu izleyerek veya CTRL+Shift+G kısayolunu “%#g” kullanarak çağırabiliyoruz. Bu fonksiyon ile Hierarchy‘de seçili olan objeye ContextMenuTest component’i ekleyebiliyoruz. Undo’nun farklı işler için farklı fonksiyonları olduğundan bahsetmiştim, component eklemek için ise AddComponent isimli generic bir fonksiyonu varmış ve ben de gördüğünüz üzere ondan faydalandım. Böylece yaptığım değişikliği Undo diyerek geri alabiliyorum.
Yazdığımız tüm bu kodları test etmek için CTRL+G ile sahnede yeni bir 5x5x5’lik küp oluşturabilir, CTRL+Shift+G‘yi iki kere kullanarak bu küp objesine iki adet ContextMenuTest component‘i ekleyebilir ve H diyerek küpü biraz yukarı taşıyabilirsiniz. Herhangi bir anda CTRL+Z veya Undo ile herhangi bir değişikliği geri alabilirsiniz. Küpte iki tane ContextMenuTest olunca fark edeceğiniz üzere her component için EditorScript2 scripti ayrı ayrı çalışıyor ve iki component’in değişkenlerinin değerleri birbiriyle karışmıyor. Ayrıca sayi değişkenini değiştirince ona bakan tüm editor field’ları da otomatik olarak güncelleniyor.
Bu derslik de bu kadar. Biraz uzunca ve biraz sıkıcı bir yazı oldu ancak umarım işinize yaramıştır. Dediğim gibi, çok fazla editör class’ı ve fonksiyonu mevcut; bunların hepsini bilmeniz mümkün değil ancak editör scripti yazmak ile ilgili tutorial izleyerek, Google’a sorular sorarak veya sırf Unity Script Reference’de oradan oraya zıplayarak bile kendinizi oldukça geliştirebilirsiniz. Bir sonraki derste görüşmek üzere!