Unity’de Yıkılabilir Duvar Yapımı (Destructible Wall)
Merhaba, bir önceki dersimizde Unity‘de pause menüsü yapımını öğrenmiştik.Böylece gayet basit bir şekilde oyunumuzu durdurabiliyor ve kaldığı yerden devam ettirebiliyorduk.Bugünkü dersimizde ise, Unity ile hasar alıp yıkılabilen bir duvar yapacağız.Bu şeklide yapmış olduğunuz projelerde, hasar alması ve parçalanması gereken nesneleri daha gerçekçi bir hale getirebiliyoruz.İsterseniz lafı uzatmadan yeni bir proje oluşturalım ve dersimize başlayalım.
Sahnemizi oluşturma süreci.
Öncelikle bu proje için kullanacağımız senaryoya bir bakalım.Sahnemizde iki temel nesnemiz yer alacak.Bunlardan birisi hasar vereceğimiz nesnemizi oluştururken diğeri ise, bu hasarı vermek için oluşturacağımız nesne olacak.İkinci nesne için pek çok varyasyon denedim.Silah, bazuka, balyoz gibi nesneler oluşturup denedikten sonra sahne için en iyisinin bir tank olacağına karar verdim.Bu yüzden duvarımızı yıkmak için bir tank kullanacağız.Şimdi geri dönecek olursak, hasar alan bir nesneyi yapmanın birden çok yolu var.
Burada ben SketchUp programında yaptığım bir duvar modelini kullanacağım.Siz internetten bulacağınız yada kendinizin yaptığı bir modeli kullanabilirsiniz.Bu duvar modelini nasıl yaptığıma gelirsek, öncelikle istediğim ölçülerde bir dikdörtgen oluşturdum.Daha sonra kalem aracını kullanarak, bu dikdörtgen üzerinde rastgele şekiller çizdim.Daha sonra çizerek oluşturduğum tüm bu parçalardan yeni bir component oluşturdum.Son olarak üç boyutlu hale getirmek için bir miktar derinlik kazandırdım.Yani gayet basit adımlar yoluyla bu modeli oluşturdum.Sonuç aşağıdaki gibidir.
Şimdi Unity‘e geri dönecek olursak, bize bir zemin gerekiyor.Bunun için Plane nesnemizi sahnemize dahil ediyoruz.Daha sonra bir Cube nesnesi oluşturuyoruz.Bu nesne tankımızın gövdesini oluşturacak.Scene penceresinden istediğimiz boyutları verdikten sonra, yeni bir Cube nesnesi daha oluşturuyoruz.Acncak burada dikkat etmemiz gereken bir nokta var.Bu yeni Cube nesnesi, tankımızın gövdesi için oluşturduğumuz nesnenin çocuğu konumunda olmalıdır.Bu önemli bir detay.İkinci Cube nesnemiz tankımızın kafa kısmını oluşturacak.Daha sonra bu nesnemizin altına, yine aynı şekilde bir Cube oluşturuyoruz.
Bu nesnede tankımızın namlusunu oluşturacak.Geri atacağımız merminin çıkacağı pozisyonu belirlemek kaldı.Bunun içinde bir boş nesne oluşturuyoruz.Burası önemli çünkü bu noktada herhangi bir collider bileşenine sahip nesne eklersek, çıkan topların gittikleri yönlerde bir tutarsızlık olacaktır.Şimdi yeni bir Sphere nesnesi oluşturuyoruz.Bu nesne tankımızdan çıkan topumuzu oluşturacak.Bu nesneye bir Rigidbody bileşeni ekliyoruz.Daha sonra yeni bir etiket oluşturuyoruz ve nesnemize ekliyoruz.Artık bu nesneyi Prefab olarak kullanabiliriz.Bunun için nesnemizi sürükleyerek, Project penceresine bırakıyoruz.Şimdi top nesnemizi sahnemizden silebiliriz.Basit bir şekilde oluşturduğumuz tankımız bu şekilde görünüyor.
Yıkılacak duvarımızı hazırlayalım.
Artık duvar modelimizi sahnemize ekleyebiliriz.Öncelikle bu modeli sağlıklı kullanabilmek için birkaç ayar yapmamız gerekiyor.Duvar nesnemizi sahnemize ekliyoruz.Daha sonra tüm parçalarını seçiyoruz.Bunu ilk parçayı seçip daha sonra shift tuşuna basılı tutarken, son parçayı seçerek yapabilirsiniz.Şimdi tüm bu parçalara yeni bileşenler ekleyeceğiz.İlk olarak attığımız top mermilerinin çarpması ve içlerinden geçmesini engellemek için, Mesh Collider bileşenini ekliyoruz.Daha sonra bu Mesh Collider bileşeninin, “Convex” özelliğini aktif hale getiriyoruz.
Bu parçanın çarpışmayı algılaması için önemli bir özelliktir.Daha sonra Rigidbody bileşenini ekliyoruz.Bu bileşen ile, duvar nesnemizin tüm parçalarına fizik unsurlarını eklemiş oluyoruz.Şimdi bu bileşenimizde bulunan “isKinematic” özelliğini aktif hale getiriyoruz.Çünkü projemizin başlattığımızda duvarımızın yıkılmasını istemiyoruz.Yıkılma mekaniğini oluşturan en önemli unsurda bu Rigidbody bileşenidir.Şimdi yıkılacak parçalarımız hazır duruma geldi.Yalnız projeyi başlattığımız zaman duvarımızın aşağıya doğru kaydığını göreceksiniz.
Bunu engellemek içinde, duvar modelimizin parent yani ebeveyn nesnesine bir Box Collider bileşeni ekliyoruz.Artık katı bir cisim haline geldiği için aşağıya doğru bir kayma olmayacaktır.Son olarak bu duvarımızı bir Prefab nesnesine çevirmemiz gerekiyor.Aksi takdirde, projeyi başlattığımız zaman parçalanmaya başlayacaktır.İşte bu yüzden duvar nesnemizi sürüklerek Project penceresine bırakıyoruz.Buradaki Prefab nesnemizde bulunan “isKinematic” özelliğini kapatmayı unutmayalım.Artık sahnemiz hazır duruma geldi.Son hali bu şekildedir.
Kodlarımızı yazmaya başlayalım.
Bu projede iki adet C# Script dosyası kullanacağız.İlk script dosyamızda duvar nesnemizin mekaniklerini oluşturacağız.İkinci script dosyamızda ise, tankımızdan atacağımız mermiler için bir mekanik oluşturacağız.Şimdi ilk script dosyamızı editör yardımı ile açalım ve kodlarımızı yazmaya başlayalım.
public float DuvarDayanikligi; public GameObject YeniDuvar;
İlk olarak kullanacağımız değişkenleri oluşturmakla başlıyoruz.Birinci satırda, float türünde bir değişken oluşturuyoruz.Bu değişken ile, duvarımızın dayanıklılık seviyesini ayarlayacağız.İkinci satırda ise, yeni bir GameObject değişkeni oluşturuyoruz.Bu değişkende ise, sahnemizi hazırlarken oluşturduğumuz Prefab nesnemizi tutacağız.
public void OnCollisionEnter (Collision Denetle) { if (Denetle.gameObject.tag == "top") { DuvarDayanikligi -= 1; Destroy (Denetle.gameObject, 2f); } }
Şimdi yeni bir OnCollisionEnter fonksiyonu oluşturuyoruz.Bu fonksiyon ile, gerçekleşen çarpışmaları tespit edeceğiz.Burada Collision tetikleyicimizi kullanıyoruz.Bununda nedeni, kullanmış olduğumuz nesnenin katı bir gövdeye sahip olmasındandır.İkinci satırda, yeni bir koşul oluşturuyoruz.Eğer duvarımız ile temas eden nesnenin etiketi “top” ise koşulumuz doğru oluyor.Üçüncü satırda, float türünde oluşturduğumuz değişkenimizin değerini bir “1” azaltıyoruz.Böylece her darbede duvarın dayanıklılığını azaltıyoruz.
Bunu “DuvarDayanikligi –;” şeklinde de yazabilirdik.İkisi de aynı kapıya çıkıyor.Dördüncü satırda ise, duvarımıza çarpan nesneyi siliyoruz.Bunu yapmak için Destroy fonksiyonundan yararlanıyoruz.Parantez içerisine bakacak olursak, virgülden sonra bir değer daha görüyoruz.Bunu yazmak zorunda değiliz.Ancak bu sefer nesnemiz duvar ile temasından sonra hemen silinir.İşte bu silinme süresini belirlemek için virgülden sonra bir değer ekliyoruz.Burada çarpışmadan iki “2” saniye sonra nesnemizi sil demiş olduk.
if (DuvarDayanikligi == 0) { Instantiate (YeniDuvar, transform.position, transform.rotation); Destroy (this.gameObject); }
Şimdi update() fonksiyonumuzun içerisine bu kodları yazıyoruz.İlk satırda yeni bir fonksiyon oluşturuyoruz.Eğer değişkenimizin değeri sıfıra “0” eşitse koşulumuz doğru oluyor.İkinci satırda, Instantiate fonksiyonundan yararlanarak yeni bir duvar klonu oluşturuyoruz.Parantez içerisinde bulunan parametrelere bakacak olursak, birinci sırada oluşturduğumuz GameObject değişkenini görüyoruz.İkinci sırada, nesnemizin position değerlerini alıyoruz.Üçüncü sırada ise, nesnemizin rotation değerlerini alıyoruz.
Böylece klon nesnemiz aynı koordinatlarda oluşuyor.Burada neden aynı nesneyi silip yerine aynı klonunu yerleştirdik diyenler olabilir.Bunun nedeni, klon nesnemizin parçalarında bulunan Rigidbody bileşeninde ki, “isKinematic” özelliğinin kapalı olmasındandır.Yani yeni duvarımız ilk aldığı darbede paramparça olacaktır.Üçüncü satırda, Destroy fonksiyonu ile ilk duvarımızı sahnemizden siliyoruz.İlk script dosyamız kullanmaya hazır duruma geldi.
Duvara fırlatacağımız topumuzun kodlarını yazalım.
Şimdi ikinci dosyamızı editör ile açalım ve kodlarımızı yazmaya başlayalım.Bu script dosyamızda duvara fırlatacağımız topların mekaniğini oluşturacağız.
public GameObject top; public GameObject TopCikisi;
İlk olarak değişkenlerimiz oluşturuyoruz.İlk satırda, yeni bir GameObject değişkeni oluşturuyoruz.Bu değişkende, duvara fırlatmak için kullanacağımız top nesnemizi tanımlayacağız.İkinci satırda ise, yine bir GameObject değişkeni oluşturuyoruz.Bu değişkende ise, topumuzun oluşacağı pozisyonların bilgisini tutacağız.Aslında bunu Transform değişkeni ile de yapabilirdik.
if (Input.GetMouseButtonDown (0)) { GameObject yeniTop = Instantiate(top, TopCikisi.transform.position, TopCikisi.transform.rotation) as GameObject; yeniTop.GetComponent<Rigidbody> ().AddRelativeForce(Vector3.forward * 5000); }
Şimdi update() fonksiyonunun içerisine bu kodları yazıyoruz.İlk satırda yeni bir koşul oluşturuyoruz.Eğer faremizin sol tuşuna basarsak koşulumuz doğru oluyor.İkinci satırda, yeni topumuzu oluşturmak için Instantiate fonksiyonunu kullanıyoruz.Az önce bu fonksiyonda kullanılan parametreleri söylemiştik.Burada yazdığımızda ise, bu sefer script dosyamızın ekli olduğu nesnenin koordinat bilgilerini almak yerine, oluşturduğumuz GameObject değişkeninde bulunan nesnenin position ve rotation değerlerini alıyoruz.
Böylece istediğimiz pozisyonda toplar klonlanıyor.Üçüncü satıra bakacak olursak, klon nesnemizde bulunan Rigidbody bileşenine ulaşıyoruz.Çünkü bu toplara bir kuvvet verip duvara fırlatmamız gerekiyor.Bunu sağlamak içinde, AddRelativeForce fonksiyonundan yardım alıyoruz.Bu fonksiyonu tercih etmemizin nedeni ise, kuvveti yerel yönde vermesidir.Evet ikinci script dosyamızda hazır duruma geldi.
Şimdi her iki C# Script dosyamızı gerekli yerlerine ekleyelim.İlk dosyamızı duvarımızın ebeveyn nesnesine sürükleyip bırakıyoruz.İkinci dosyayı ise, tankın kafa kısmını oluşturan nesnemizin üzerine sürükleyip bırakıyoruz.Şimdi her iki script dosyamızda yer alan ilgili bölümlere oluşturmuş olduğumuz Prefab nesnelerini ekliyoruz.Daha sonra topumuzun çıkacağı nesneyi ekliyoruz.Son olarak ise, duvarımız için dayanıklılık değerini belirliyoruz.Artık projemizi test edebiliriz.Evet bir sonraki yazıda görüşmek üzere…