Unity’de Yerden Nesne Almak (Pick Up & Place)

Unity’de Yerden Nesne Almak (Pick Up & Place)

20 Şubat 2020 0 Yazar: Ahmet Güler

Merhaba, bir önceki yazımızda Unity‘de sonsuz yol yapmıştık.Bu Endless runner tarzı projeyi yaparken, nesnelerin Transform özellikleri ile oynayarak sonsuz yolumuzu oluşturmuştuk.Bu dersimizde ise, Unity ile yerden silah alma yada herhangi bir nesneyi nasıl alabileceğimize bakacağız.Kısaca bir, pick up-place projesi yapacağız.Lafı uzatmadan yeni bir proje oluşturalım ve dersimize başlayalım.

Sahnemize gereken nesnelerin eklenmesi.

Bu derste kullanacağımız senaryo şu şekilde olacak.Sahnede bir robot modelimiz olacak.Sahnenin her iki noktasında da, bir kontrol noktası olacak.Bu noktaların birinde taşıyacağımız nesneler yer alacak.Biz bu nesneleri robotumuzu kontrol ederek, diğer kontrol noktasına taşıyacağız.İşte bu kadar.Şimdi sahnemize Plane nesnesini ekleyerek başlayalım.Bu nesne zeminimizi oluşturacak.

Sonra kontrol noktalarını oluşturmaya başlıyoruz.Bunun için Cylinder ve Cube nesnelerinden yararlanıyoruz.İki tane Cube nesnesi olması gerekiyor.Cube nesnemizin bir tanesinin rampa olarak kullanacağız.Diğerini ise, yerden alacağımız nesnelerin duracağı zemin olarak kullanacağız.Silindir nesnemiz ise, zemin ortasında yer alacak.Benim sahnemde şu şekilde oluşturdum.

Unity-Yerden-Silah-Nesne-Almak-Ho-To-Pick-Up-And-Move-Objects

Daha sonra bu kontrol noktasından bir tane kopya alıyoruz ve hemen karşısına konumlandırıyoruz.İki noktamızda hazır duruma geldi.Bu noktalardan birinin üzerine yerden alacağımız nesneleri yerleştireceğiz.Bunun için, sahnemize yeni bir Cube nesnesi ekliyoruz.Daha sonra bu nesne için yeni bir etiket oluşturuyoruz ve ekliyoruz.

Şimdi bu Cube nesnemizin fizik unsurlarından etkilenmesi gerekiyor ki, yerden aldığımızda yada yere bıraktığımızda bir kuvvet verebilsin.Bunun için Inspector penceresinden Rigidbody bileşenini nesnemize ekliyoruz.Artık fizik unsurlarından etkilenebilecek.Bu Cube nesnemizden istediğimiz kadar kopya alıyoruz ve herhangi bir kontrol noktasına yerleştiriyoruz.

Unity-Yerden-Silah-Nesne-Almak-Ho-To-Pick-Up-And-Move-Objects

Şimdi kontrol edeceğimiz nesneye gelelim.Ben internetten bulduğum bir robot modelini kullanacağım.Siz başka bir modelde kullanabilirsiniz yada hiç model kullanmadan da bu işi yapabilirsiniz.Ben model kullanmadan nasıl yapacağımızı anlatacağım.İlk olarak bir boş nesneye ihtiyacımız var.Ancak konumlandırmada sıkıntı olmaması ve daha rahat konumlandırmamız için, bir Cube nesnesi kullanacağız.

Sahnemize eklediğimiz bu nesneyi, yerden aldığımız nesnenin hangi pozisyonda durmasını istiyorsak o konuma getiriyoruz.Yani benim kullanacağım modelde, robotun kolları arasına konumlandırıyorum.Böylece yerden aldığım nesneler bu noktada gözükecek.Daha sonra bu Cube nesnesinin Mesh Filter ve Mesh Renderer bileşenlerini siliyorum.Geriye bir tek Box Collider bileşeninin kalması gerekiyor.Çünkü çarpışmayı kontrol etmemiz gerekecek.Bunun içinde, “isTrigger” özelliğini aktif hale getiriyoruz.

Daha sonra bu nesne için yeni bir etiket oluşturuyoruz ve ekliyoruz.Buraya kadar projemizin sahne kısmı hazır.Ancak ben ekstra olarak FPS kamerası ve kol animasyonu da oluşturdum.Bunları yapmakta oldukça basit.Yine iki boş nesneden yararlanacağız.Bunlardan birini Kamera açımızı ayarlamak için kullanacağız.Ben robotun tam kafasına göre ayarladım.Böylece kameramız o konuma gelecek.Kol animasyonu içinde, yine ikinci boş nesnemizi gövdenin ortasına konumlandırıyoruz.

Daha sonra her iki kolu, bu nesnenin çocuğu konumuna getiriyoruz.Siz eğer bir model kullanmayacaksınız bu animasyon bölümünü pas geçebilirsiniz.Ancak kamerayı kullanacağınızı varsayıyorum.Hierarchy penceresinde hareket edecek nesne için oluşturduğumuz bütün elemanları, tek bir boş nesne altında topluyoruz.Daha sonra bu boş nesneye bir Rigidbody bileşeni ekliyoruz.Ve son olarak, bu iki boş nesneye de yeni etiketler oluşturuyoruz.İstediğimiz kaplamaları nesnelerimize ekledikten sonra artık sahnemiz hazır.Son hali bu şekildedir.

Unity-Yerden-Silah-Nesne-Almak-Ho-To-Pick-Up-And-Move-Objects

Kodlarımızı yazmaya başlayalım.

Bu projede iki adet C# Script dosyası kullanacağız.İlk script dosyamızda, yerden nesne almak için kodlarımızı yazacağız.İkinci dosyada ise, nesnemizin hareketini için kodlarımızı yazacağız.Şimdi ilk script dosyamızı editör yardımı ile açalım ve kod yazmaya başlayalım.

public Camera Kamera;
public Transform RobotKafasi;
public GameObject RobotKollari;
public GameObject Nesne;
public Transform TasimaNoktasi;
public bool nesneAktifMi;
public bool MaxKapasite;

İlk olarak değişkenlerimizi oluşturmakla başlıyoruz.Birinci satırda, kamera nesnemiz için bir değişken oluşturuyoruz.İkinci satırda, bir Transform değişkeni oluşturuyoruz.Bu değişkende kameramızın geleceği Transform bilgilerini tutacağız.Üçüncü satırda, kontrol edeceğimiz modelin kolları için bir GameObject değişkeni oluşturuyoruz.Dördüncü satırda yine bir GameObject değişkeni oluşturuyoruz.

Bu değişkende ise, yerden aldığımız nesneyi kontrol edeceğiz.Beşinci satırda ise, yerden aldığımız nesnenin duracağı konum için bir Transform değişkeni oluşturuyoruz.Altıncı ve yedinci satırlarda ise, bool türünde değişkenler oluşturuyoruz.Bu değişkenlerde taşıyabileceğimiz maksimum nesneyi ve nesneyi alıp almadığımızı kontrol edeceğiz.

Kamera = Camera.main;
RobotKafasi = GameObject.FindWithTag ("kafa").transform;
Kamera.transform.SetParent(RobotKafasi);
Kamera.transform.localPosition = new Vector3(0.95f, 0, RobotKafasi.transform.position.z);
Kamera.transform.localRotation = Quaternion.Euler(25f, -90f, RobotKafasi.transform.rotation.z);
Kamera.fieldOfView = 74f;
RobotKollari = GameObject.FindWithTag ("kollar");
TasimaNoktasi = GameObject.FindWithTag ("tasimaNoktasi").transform;
nesneAktifMi = false;
MaxKapasite = false;

Şimdi start() fonksiyonumuzun içerisine bu kodları yazıyoruz.İlk satırda, değişkenimize ana kameramızı tanımlıyoruz.İkinci satırda etiketi “kafa” olan nesnenin Transform özelliklerini, değişkenimize tanımlıyoruz.Üçüncü satırda kameramızı SetParent fonksiyonu ile parantez içerisindeki değişkenimizin, çocuk nesnesi yapıyoruz.Dördüncü satırda kamera nesnemizin pozisyonunu, localPosition fonksiyonunu kullanarak istediğimiz şekilde ayarlıyoruz.

Beşinci satırda ise yine kameramızın açısını, bu sefer localRotation fonksiyonu ile ayarlıyoruz.Ben modelime göre bir ayar yaptım.Siz kendinize göre düzenlemelisiniz.Altıncı satırda kameramızın görüş açısını, fieldOfView fonksiyonu ile düzenliyoruz.Burada biraz daha geniş bir açı elde ettik.Altıncı satırda, etiketi “kollar” olan nesneyi değişkenimize tanımlıyoruz.

Yedinci satırda, etiketi “tasimaNoktasi” olan nesnenin Transform özelliklerini değişkenimize tanımlıyoruz.Burada transform yazmasaydık hata alacaktık.Çünkü oluşturduğumuz değişken GameObject değilde bir Transform değişkenidir.Sekizinci ve dokuzuncu satırlarda ise, bool değişkenlerimizin değerlerini false olarak belirliyoruz.

void TasimaKontrolu() {
   nesneAktifMi = !nesneAktifMi;
}

Şimdi yeni bir fonksiyon oluşturuyoruz.Bu fonksiyonda, bool değişkenimizin true ve false durumunu kontrol edeceğiz.İkinci satırda yaptığımız şey eğer değişkenimizin değeri true ise, false yap.Tam tersi ise de true yap.Bu kod ile tek bir tuş yardımı ile bool türündeki değişkenlerinizin değerini değiştirebilirsiniz.

void RobotKolAnimasyonu() {
   if (Nesne == null) {
      RobotKollari.transform.localRotation = Quaternion.Euler(0, 0, 40f);
   }
}

Yine yeni bir fonksiyon oluşturuyoruz.Bu fonksiyonda ise, kollar için bir animasyon yapacağız.İkinci satırda yeni bir koşul oluşturuyoruz.Eğer “Nesne” değişeni boş ise, koşulumuz doğru oluyor.Üçüncü satırda, localRotation fonksiyonundan yararlanarak z eksenindeki açısını, kırk “40” olarak değiştiriyoruz.Tabi bu benim kullandığım modele göre ayarlandı.Siz kendinize göre ayarlayabilirsiniz.

Nesneleri yerden almak.

void OnTriggerStay(Collider Denetim) {
   if (Denetim.gameObject.tag == "kutu" && nesneAktifMi && !MaxKapasite) {
      Nesne = Denetim.gameObject;
      Denetim.transform.SetParent(TasimaNoktasi);
      Denetim.transform.position = TasimaNoktasi.transform.position;
      Denetim.transform.rotation = TasimaNoktasi.transform.rotation;
   }
}

Nesneleri ile çarpışmayı kontrol etmek için yeni bir OnTriggerStay fonksiyonu oluşturuyoruz.Sürekli olarak çarpışmayı denetlemek için Stay fonksiyonunu tercih ettim.İkinci satırda, yeni bir koşul oluşturuyoruz.Bu koşulda üç denetim yapacağız.Eğer bunların hepsi doğru ise, koşulumuz aktif olacak.İlk olarak nesnemizin etiketi “kutu” olmalıdır.İkinci olarak, “nesneAktifMi ” bool türündeki değişkenimizin değeri true olmalıdır.

Son olarak da, “MaxKapasite” bool türündeki değişkenimizin değeri false olmalıdır.Üçüncü satırda değişkenimize, çarpışma ile bulduğumuz nesneyi tanımlıyoruz.Dördüncü satırda ise, SetParent fonksiyonu ile parantez içerisindeki değişkenimizin, çocuk nesnesi yapıyoruz.Beşinci ve altıncı satırlarda, çarpışma ile bulduğumuz nesnenin pozisyonunu ve açısını, parent yani ebeveyn nesnemizin değerlerine eşitliyoruz.

RobotKollari.transform.localRotation = Quaternion.Euler(0, 0, 0);
Denetim.GetComponent<Rigidbody> ().isKinematic = true;
MaxKapasite = true;

Koşulumuzun devamına bu kodları yazıyoruz.İlk satırda kol animasyonu için oluşturduğumuz değişkeni kullanarak, kollarımızın açısını yeniden ayarlıyoruz.İkinci satırda, çarpışma sağlanan nesnenin Rigidbody bileşenine erişerek “isKinematic” özelliğini true konumuna getiriyoruz.Son satırda ise, bool türündeki değişkenimizin değerini true olarak belirliyoruz.

void NesneyiAlBirak() {
   if (Input.GetKeyDown(KeyCode.E)) {
      TasimaKontrolu ();
      if (Nesne != null && !nesneAktifMi) {
         Nesne.GetComponent<Rigidbody> ().isKinematic = false;
         Nesne.transform.parent = null;
      }
   }
}

Şimdi yeni bir fonksiyon oluşturuyoruz.Bu fonksiyonda yerden nesne almak ve bırakmak için kontrol mekanizmasını oluşturacağız.İkinci satıra bakacak olursak, yeni bir koşul oluşturuyoruz.Eğer klavyeden “E” tuşuna basılırsa, koşulumuz aktif oluyor.Üçüncü satırda, bool değişkenimiz için oluşturduğumuz fonksiyonu çağırıyoruz.Dördüncü satırda, yeni bir koşul oluşturuyoruz.

Eğer “Nesne” değişkenimiz boş değilse ve “nesneAktifMi” bool değişkenimizin değeri false ise koşulumuz doğru oluyor.Beşinci satırda, değişkenimizde tanımlı olan nesnenin Rigidbody bileşenine ulaşıyoruz ve “isKinematic” özelliğini false konumuna getiriyoruz.Böylece nesnemiz fizik unsurlarından etkileniyor.Altıncı satırda ise, değişkenimizde tanımlı nesnemizin parent nesnesinden kurtarıyoruz.

Nesne = null;
MaxKapasite = false;
RobotKolAnimasyonu ();

Daha sonra bu kodları devamına yazıyoruz.İlk satırda, değişkenimizi değerini null yapıyoruz.Yani tanımlı bir nesne varsa onu siliyoruz.İkinci satırda, bool türündeki değişkenimizin değerini false konumuna getiriyoruz.Böylece yerden yeni bir nesne alabileceğiz.Son satırda ise, kol animasyonu için oluşturduğumuz fonksiyonu çağırıyoruz.Böylece yerde kutu aldığımızda kalkan kollarımız, kutuyu bıraktığımız zaman eski konumuna dönüyor.

NesneyiAlBirak ();

Son olarak tüm bu mekaniklerin çalışması için, update() fonksiyonunun içerisine bu kodu yazıyoruz.Böylece fonksiyonumuz her karede çalışıyor ve beraberinde diğer kodları ve fonksiyonları çalıştırıyor.Evet ilk script dosyamız hazır.

Hareket mekaniklerini oluşturmaya başlayalım.

İlk script dosyamızda nesne ile etkileşim için gereken mekanikleri oluşturmuştuk.İkinci dosyamızda ise, kontrol edeceğimiz nesne için bir hareket mekaniği oluşturacağız.Şimdi script dosyamızı editör ile açalım ve kod yazmaya başlayalım.

public float RobotHizi;

İlk olarak değişkenimizi oluşturmakla başlıyoruz.Burada float türünde bir değişken oluşturuyoruz.Bu değişken ile hareket ettireceğimiz nesnenin hızını kontrol edebileceğiz.

RobotHizi = 3f;

Daha sonra start() fonksiyonumuzun içerisine bu kodu yazıyoruz.Burada ise, değişkenimize başlangıç için bir değer atıyoruz.

transform.Translate (Input.GetAxis("Vertical")*Vector3.forward*RobotHizi*Time.deltaTime); 
transform.Rotate(0f, Input.GetAxis ("Horizontal") * RobotHizi, 0f);

Şimdi update() fonksiyonumuzun içerisine bu kodları yazıyoruz.Bu kodları daha önceki yazılarımı okuduysanız sıkça karşılaşmışsınızdır.Yalnız bu sefer ufak bir değişiklik yaptım.İlk satırda, Translate fonksiyonunu kullanarak dikey eksende nesnemizin hareketini sağlıyoruz.Tabi bunu yaparken, hız için oluşturduğumuz değişken ve Time.deltaTime fonksiyonu ile de çarpıyoruz.

Böylece her karede belirli bir hız yakalıyoruz.İkinci satırda ise, bu sefer Rotate fonksiyonunu kullanıyoruz.Bu fonksiyon ile yatay eksendeki hareketi sağlamak yerine açıyı sağlıyoruz.Böylece döndüğümüz yöne doğru ileri veya geri hareketini gerçekleştirebiliyoruz.Tabi bu projede sadece y ekseni için geçerli oluyor.Böylece ikinci script dosyamızı da tamamlamış oluyoruz.Son hali aşağıdaki gibidir.

Evet projemizi tamamlamış bulunuyoruz.Şimdi oluşturduğumuz bu iki C# Script dosyamızı gerekli yerlere ekliyoruz.İlk script dosyamızı, hareket edecek modelimizin ebeveyn nesnesine ekliyoruz.İkinci script dosyasını ise, yerdeki nesnelerin çarpışma sonucu transform özelliklerinin eşitleneceği nesneye ekliyoruz.Artık hazırız.Bir sonraki yazıda görüşmek üzere..

Unity-Yerden-Silah-Nesne-Almak-How-To-Pick-Up-And-Move-Objects