Unity’de Ara Sahne Yapımı (CutScene)

Unity’de Ara Sahne Yapımı (CutScene)

11 Şubat 2020 0 Yazar: Ahmet Güler

Merhaba, bir önceki yazımızda Unity‘de kamerayı nasıl sarsabileceğimizi öğrenmiştik.Bu dersimizde ise, ara sahne yapımını göreceğiz.Ara sahneler, oyunlarda bölümler arası geçiş, bir mekaniğe yada nesneye dikkat çekme gibi çeşitli amaçlarla kullanılırlar.Şimdi yeni bir proje oluşturalım ve dersimize başlayalım.

Sahnemizin hazırlanması.

Öncelikle bu projemizdeki senaryoyu açıklayayım.Basit bir parkur oluşturacağız.Daha sonra çeşitli pozisyonlara, nesneler koyacağız.Bir tetikleyici yardımı ile, kameramız bu noktaları sırasıyla takip ederek eski konumuna dönecek.Böylece ara sahnemiz tamamlanmış olacak.Şimdi sahnemize bir Plane nesnesi ekleyerek başlayalım.Bu nesneye yeni bir etiket oluşturalım.Daha sonra çarpışmayı algılamak için bir Cube nesnesi oluşturalım.Bu nesne ara sahnemizi başlatacak.

Nesnemizin collider bileşeninde bulunan “isTrigger” özelliğini aktif hale getirelim.Çünkü bu nesneyi sadece tetikleyici olarak kullanacağız.Yani MeshRenderer bileşeni kapalı olacak ve sahnemizde görünmeyecek.Şimdi bir Cube nesnesi daha oluşturalım.Bu nesne bizim oyuncumuz olacak.Cube nesnemize bir Rigidbody bileşeni ekliyoruz.Tetikleyici kodumuzun çalışması için katı bir nesneye ihtiyacımız var.Daha sonra yeni bir etiket oluşturuyoruz ve ekliyoruz.Şimdi kameramız için bir yol oluşturacağız.Bunu Create Empty yani boş nesneler ile yapabilirsiniz.

Ancak ben daha iyi görmeniz için, Cube nesneleri ile yapacağım.Kameramızın gideceği pozisyonlara, nesnelerimizi konumlandırıyoruz.Daha sonra tüm bu nesneler için yeni bir etiket oluşturuyoruz.Ve bu etiketi hepsine ekliyoruz.Burası önemli çünkü birazdan bu nesneleri listeye ekleyeceğiz.Artık hazırız.Başta parkur yapacağımı söylemiştim.Bunun için ekstra olarak nesneler, modeller ve kaplamalar kullandım.Ancak bunlar sadece sahnemin görselliği için kullanıldı.Mekanik olarak hiçbir katkısı yok.Yukarıda oluşturduğumuz sahne bizim için yeterli olacaktır.Benim sahnemin son hali bu şekildedir.

Unity-Ara-Sahne-Yapımı-CutScene-tutorial

Kameramızın izleyeceği yolu yapalım.

Bu proje için iki adet C# Script dosyası kullanacağız.İlk script dosyamız ile ara sahnemizin animasyonunu oluşturacağız.İkinci dosya ile de, oyuncumuz için basit bir hareket mekaniği oluşturacağız.Şimdi dosyamızı açalım ve kod yazmaya başlayalım.

using System.Linq;

İlk olarak script dosyamızın en başında bulunan kütüphaneler arasına, bu kütüphaneyi de dahil ediyoruz.Bu kütüphane aslında yaptığımız projelerde bizim işimizi çok kolaylaştırıyor.Bir çok faydası olmakla beraber, genellikle listeleme gibi işlemlerde kullanılıyor.Bizde bu amaçla kullanacağız.

public Camera KameraNesnesi;
public GameObject Harita;
public List<Transform> KameraNoktalari = new List<Transform>();
public Transform HareketNoktasi;
public int SiradakiNokta;
public float Hiz;
public float GecenSure;
public float MaksimumSure;
public bool araSahneAktif;

Evet şimdi değişkenlerimiz oluşturmaya başlayalım.İlk satırda, kamera nesnemiz için bir değişken oluşturuyoruz.İkinci satırda, kameramızın izleyeceği nesnemiz için bir değişken oluşturuyoruz.Üçüncü satırda, bir Transform listesi oluşturuyoruz.Bu listede kameramızın takip edeceği nesnelerin pozisyonlarını tutacağız.Dördüncü satırda, yeni bir Transform değişkeni oluşturuyoruz.Bu değişkenimizde ise, kameramızın hangi nesnenin pozisyonuna gittiğini takip edeceğiz.

Beşinci satırda, int (integer) türünde bir değişken oluşturuyoruz.Bu değişken bize, takip sırası için numara verecek.Altıncı satırda, float türünde bir değişken oluşturuyoruz.Kameramızın hareket hızını bu değişken ile kontrol edeceğiz.Yedinci ve sekizinci satırlarda, noktalar arasında kameramızın beklemesi için değişkenler oluşturuyoruz.Son satırda ise, bool türünde bir değişken oluşturuyoruz.Bu değişken ara sahnemizin başlatılmasını kontrol edecek.

KameraNesnesi = Camera.main;
foreach (GameObject TumNoktalar in GameObject.FindGameObjectsWithTag("noktalar")) {
   KameraNoktalari.Add(TumNoktalar.GetComponent<Transform>());
}
KameraNoktalari = KameraNoktalari.OrderBy(AdaGoreSirala=>AdaGoreSirala.name).ToList();
HareketNoktasi = KameraNoktalari[SiradakiNokta];
Harita = GameObject.FindWithTag ("harita");
SiradakiNokta = 0;
Hiz = 10;
MaksimumSure = 0.1f;

Şimdi start() fonksiyonunun arasına bu kodları yazıyoruz.İlk satırda, ana kameramızı (Main Camera) değişkene tanımlıyoruz.İkinci satırda, yeni bir foreach döngüsü oluşturuyoruz.Bu döngüde FindGameObjectsWithTag fonksiyonu ile, etiketi “noktalar” olan tüm nesneleri topluyoruz.Üçüncü satırda, oluşturduğumuz listeye bu nesnelerin Transform özelliklerini ekliyoruz.

Beşinci satırda, listemizdeki bu nesneleri ad sırasına göre yerleştiriyoruz.Bunu yapmak için az önce yeni bir kütüphane eklemiştik.İşte tek satırda, listeleme işlemini başarı ile gerçekleştiriyoruz.Eğer bunu yapmazsak, listemiz rastgele olarak oluşacak ve projemizi başlattığımız zaman kameramız istemediğimiz bir noktaya gidecek.Altıncı satırda, kameramızın gideceği başlangıç noktasını belirliyoruz.

Yedinci satırda, kameramızın takip edeceği nesneyi tanımlıyoruz.Burada etiketi “harita” olan nesnemiz oluyor.Sekizinci satırda, değişkenimize sıfır “0” değerini veriyoruz.Dokuzuncu satırda, kamera hızımız için bir değer oluşturuyoruz.Son satırda ise, süremiz için bir değer oluşturuyoruz.Ben çok az bir bekleme olması açısından böyle bir değer verdim.Süreyi arttırdıkça kameramız, noktalar üzerinde daha çok bekleyecektir.

void KameraDonusleri() {
   Vector3 Yon = HareketNoktasi.position - KameraNesnesi.transform.position;
   float DonusHizi = Hiz * Time.deltaTime;
   Vector3 YeniYon = Vector3.RotateTowards(transform.forward, Yon, DonusHizi, 0.0f);
   Debug.DrawRay(KameraNesnesi.transform.position, Yon, Color.red, 5f);
   KameraNesnesi.transform.rotation = Quaternion.LookRotation(YeniYon);
   KameraNesnesi.transform.LookAt (Harita.transform);
}

Şimdi yeni bir fonksiyon oluşturuyoruz.Bu fonksiyon ile, kameramızın dönüş açılarını kontrol edeceğiz.İkinci satırda, yönü hesaplamak için bir Vector3 değişkeni oluşturuyoruz.Daha sonra kamera ile gideceği noktanın pozisyonunu birbirlerinden çıkartarak farkı buluyoruz.Üçüncü satırda, dönüş hızı için bir değişken oluşturuyoruz.

Dördüncü satırda, RotateTowards fonksiyonu ile kameramızın yönünü hedef doğrultusunda döndürüyoruz.Beşinci satırda, DrawRay fonksiyonu ile kameramızın gideceği doğrultuyu çiziyoruz.Tabi bu sadece Scene penceresinde görünecektir.Altıncı satırda ise kameramızın açısını, yeni pozisyonumuza göre değiştiriyoruz.Son satırda, kameramızın yönünü LookAt fonksiyonu ile haritamıza çeviriyoruz.

Hedef noktalara sırasıyla kamerayı taşımak.

void AraSahneyiBaslat (){
   if (GecenSure < MaksimumSure) {
      GecenSure += Time.deltaTime;
   } else {
      float KameraHizi = Hiz * Time.deltaTime;
      KameraNesnesi.transform.position = Vector3.MoveTowards (KameraNesnesi.transform.position, HareketNoktasi.position, KameraHizi);
      KameraDonusleri ();
   }
   if (KameraNesnesi.transform.position == HareketNoktasi.position) {
      GecenSure = 0;
      if(SiradakiNokta >= KameraNoktalari.Count-1) {
         SiradakiNokta=0;
         araSahneAktif = false;
      } else {
         SiradakiNokta++;
      }
      HareketNoktasi = KameraNoktalari[SiradakiNokta];
   }
}

Evet yeni bir fonksiyon daha oluşturuyoruz.Bu fonksiyonun amacı ise, listemizde yer alan noktalara kameramızı sırasıyla götürmek.İkinci satırda yeni bir koşul oluşturuyoruz.Eğer süremiz maksimum süreden küçük ise, koşulumuz çalışıyor.Üçüncü satırda süre değişkenimizi, Time.deltaTime fonksiyonu ile her karede aynı olacak şekilde arttırıyoruz.Eğer süremiz artık maksimum süreden küçük değilse, o zaman else tarafındaki kodlar aktif oluyor.Beşinci satırda, yeni bir değişken oluşturuyoruz.Bu değişken ile hızımızı kontrol edeceğiz.

Altıncı satırda ise MoveTowards fonksiyonunu kullanarak, iki nokta arasındaki hareketi sağlamış oluyoruz.Böylelikle kameramızı noktalar arasında hareket ettirebiliyoruz.Yedinci satırda, biraz önce oluşturduğumuz fonksiyonu çağırıyoruz.Bu şekilde kameramız, hem hareket ediyor hemde açısını değiştirmiş oluyor.Dokuzuncu satırda, yeni bir koşul oluşturuyoruz.Eğer kameramız hedef noktaya ulaşmış ise, koşulumuz doğru oluyor.Onuncu satırda, süre değişkenimizi sıfırlıyoruz.Onbirinci satırda tekrar yeni bir koşul oluşturuyoruz.

Burada ise listemizde yer alan noktalardani sonuncusuna ulaşıp ulaşmadığımızı kontrol ediyoruz.Liste elemanları sıfırdan “0” başladığı için, koşulumuzun sonuna “-1” ekledik.Böylece hata vermeyecektir.Onikinci satırda, değişkenimizi sıfırlıyoruz.Böylece listemiz başa dönüyor.Onüçüncü satırda, bool değişkenimizi false değerine eşitliyoruz.Onbeşinci satırda ise, eğer listemizin sonuna gelmediysek, değişkenimizi bir “1” arttırarak devam ediyoruz.Onyedinci satırda, kameramızın yeni hareket noktasını belirliyoruz.

void OnTriggerEnter(Collider Tetikle) {
   if (Tetikle.gameObject.tag == "oyuncu") {
      araSahneAktif = true;
   }
}

Yeni bir tetikleyici fonksiyonu oluşturuyoruz.OnTriggerEnter fonksiyonu ile oyuncumuzun çarpışmasını algılayıp, ara sahnemizi başlatabileceğiz.İkinci satırda, etiketi “oyuncu” olan nesne eğer tetikleyici nesnemiz ile temas ettiyse koşulumuz doğru oluyor.Üçüncü satırda ise, bool değişkenimize true değerini veriyoruz.Böylece ara sahnemiz başlaması için komut veriyoruz.

public void Update() {
   if (araSahneAktif) {
      AraSahneyiBaslat ();
   }
}

Son olarak, update() fonksiyonunun içerisine bu kodları yazıyoruz.İkinci satırda yeni bir koşul oluşturuyoruz.Eğer bool değişkenimizin değer true ise koşulumuz doğru oluyor.İkinci satırda, kameramızın hareketi için oluşturduğumuz fonksiyonu çağırıyoruz.Evet bu script dosyamız hazır.

Oyuncumuzun hareketini oluşturalım.

public float OyuncuHizi = 5f;

void Update () {
   transform.Translate (Input.GetAxis("Vertical")*Vector3.forward*OyuncuHizi*Time.deltaTime); 
   transform.Translate (Input.GetAxis("Horizontal")*Vector3.right*OyuncuHizi*Time.deltaTime);
}

Evet ikinci script dosyamıza bu kodları yazıyoruz.İlk olarak bir değişken oluşturuyoruz.Bu değişken ile oyuncu nesnemizin hareket hızını ayarlayacağız.Daha sonra update() fonksiyonu içerisine, Translate fonksiyonlarını yazıyoruz.Böylece nesnemiz, hem dikey hemde yatay eksende hareket kabiliyeti kazanmış oluyor.Burayı kısa geçiyorum.İsteyen önceki yazılarımdan daha detaylı bir bilgi alabilir.Evet bu script dosyamızı da hazırlamış bulunmaktayız.

Son olarak ilk script dosyamızı, tetikleyici nesnemizin üzerine sürükleyip bırakalım.İkinci script dosyasını ise, oyun nesnemizin üzerine sürükleyip bırakalım.Artık projemiz hazır duruma geldi.Kodlarımız arasına birçok mekanik eklenebilir.Ancak ben yazının konusundan çıkmamak için, en temel unsurları ekledim.Evet, bir sonraki yazıda görüşmek üzere…

Unity-Ara-Sahne-Yapımı-CutScene-tutorial