Unity’de Joystick Yapımı
Merhaba, bir önceki yazımızda Unity‘de nesnemize yol takibi yaptırmıştık.Böylece noktasal bir hareket mekaniği elde etmiştik.Bugünkü dersimizde ise, Unity ile joystick yapımına bakacağız.Yalnız bu derste sadece, joystick için UI yani arayüz tasarımı ve hareket mekaniği üzerinde duracağız.Bir nesneyi joystick ile kontrol etmeyi ise başka bir derste anlatacağım.Şimdi vakit kaybetmeden yeni bir proje oluşturalım ve dersimize başlayalım.
Joystick için kullanacağımız arayüz tasarımına başlayalım.
İlk olarak yeni bir Canvas oluşturuyoruz.Daha önceki yazılara bakacak olursanız, ayrıntılı olarak arayüz elemanları üzerinde durmuştuk.Bu yüzden kısa geçiyorum.Şimdi bu Canvas elemanımızın boyutunu ayarlamamız gerekiyor.Burası önemli bir aşama.Çünkü her ekran çözünürlüğünde, ekranda görünecek arayüz elemanları aynı pozisyonda görünmesi gerekiyor.
Bunu sağlamak için, Canvas elemanı seçili iken, Inspector penceresinde “Canvas Scaler” bileşenini buluyoruz.Daha sonra, “UI Scale Mode” özelliğini Scale With Screen Size moduna getiriyoruz.Hemen altında açılan yeni çözünürlük yani “Reference Resolution” bölüme istediğimiz bir çözünürlüğü giriyoruz.Tavsiyem FullHD yani “1920×1080” olarak belirlemeniz.Evet çözünürlüğü ayarladığımıza göre devam edebiliriz.Şimdi Canvas elemanını seçiyoruz ve sağ tıklayarak sırasıyla “UI > Image” seçimini yapıyoruz.
Bu image elemanı, joystick için bir arkaplan oluşturacak.Yeni bir etiket oluşturarak bu elemanımıza ekliyoruz.Daha sonra Inspector penceresinde bulunan Rect Transform bileşeninde, arkaplan için bir boyut ve pozisyon belirliyoruz.Pozisyonu belirlerken kolaylık olması açısından, aynı bileşende “Custom” yazan bir kare göreceksiniz.O kareye bastığınızda çeşitli noktalar önünüze açılacak.Klavyeden alt tuşuna basılı tutarak bir seçim yaparsanız, image elemanınız o pozisyona gidecektir.
Daha sonra ekran ile arkaplan arasında boşluk bırakmak için, PosX ve PosY özelliğini kullanıyoruz.Daha sonra bu image elemamız seçili iken sağ tıklıyoruz ve yine “UI > Image” seçimini yapıyoruz.Bu eleman ise, joystick butonumuzu oluşturacak.Bu eleman içinde yeni bir etiket oluşturuyoruz.Bu image elemanımız içinde boyut ayarını istediğimiz gibi yapıyoruz.Sahnemizin bu aşamadaki hali aşağıdaki gibidir.
Buraya kadar arayüz tasarımını ve gereken ayarları yaptık.Şimdi bu image elemanlarına bir görsel atayacağız.Bu görselleri internetten bulabilirsiniz.Yada kendiniz tasarlayabiliriniz.Ben internetten bir tane seçtim.Bu projede onu kullanacağım.İlk olarak joystick için belirlediğimiz buton ve arkaplan resimlerini projemize dahil ediyoruz.Daha sonra bu resimleri tek tek seçiyoruz ve Inspector penceresinde bulunan, Texture Type özelliğini “Sprite (2D and UI)” moduna getiriyoruz.Daha sonra biraz aşağıda bulunan, Alpha Is Transparency özelliğini aktif ediyoruz.Böylece resimlerimizde saydam olan yerler açığa çıkıyor.
Evet joystick üzerinde kullanacağımız resimler artık hazır.Şimdi Canvas içerisinde bulunan Image elemanlarını tek tek seçerek, Inspector penceresinde bulunan Source Image bölümüne, Project penceresindeki resimleri sürükleyip bırakıyoruz.Artık joystick görsel olarak hazır duruma geldi.Bu arada, Camera nesnemizin Clear Flags özelliğini, “Solid Color” moduna getiriyoruz.Joystick elemanımızı denerken, küçük bir mekanik yapacağız.Evet, sahnemizin son hali bu şekildedir.
Joystick için kodlarımızı yazmaya başlayalım.
Evet şimdi yeni bir C# Script dosyası oluşturuyoruz.Bu dosyaya yeni bir isim verdikten sonra editör yardımı ile açıyoruz.Artık kodlarımızı yazmaya başlayabiliriz.
using UnityEngine.UI; using UnityEngine.EventSystems;
İlk önce bu iki kütüphaneyi script dosyamıza ekliyoruz.İlk satırda, sahnemizdeki UI elemanlarına erişmek için bir kütüphane ekliyoruz.İkinci satırda ise, bu joystick elemanını kontrol edebilmek için bir kütüphane ekliyoruz.
IDragHandler, IPointerDownHandler, IPointerUpHandler
Daha sonra bu kodları script dosyamıza dahil ediyoruz.Bu kodların her biri, farklı bir giriş işleminden sorunlu olacak.İlki joystick butonumuz hareket ettiği zaman geri bildirim verecek.İkincisi joystick butonumuzu kullanırken geri bildirim verecek.Sonuncusu ise, joystick butonumuzu bıraktığımız zaman geri bildirim verecek.EventSystems kütüphanesi ile bu özelliklere erişebiliyoruz.
public Image Arkaplan; public Image Buton; public int ButonCapi; public Vector3 KoordinatXYZ; public Vector2 KoordinatXY; public float xEkseni; public float yEkseni;
Artık değişkenlerimizi oluşturmaya başlayabiliriz.İlk ve ikinci satırlarda, Image değişkenleri oluşturuyoruz.Bu değişkenlerde sahnemizdeki UI elemanlarını kontrol edebileceğiz.Üçüncü satırda int (integer) türünde bir değişken oluşturuyoruz.Bu değişken ile, joystick butonumuzun yarıçap sınırını belirleyebileceğiz.Dördüncü satırda, Vector3 değişkeni oluşturuyoruz.
Bu değişende, joystick butonumuzun dünya üzerindeki koordinatlarını takip edeceğiz.Beşinci satırda ise bir Vector2 değişkeni oluşturuyoruz.Bu değişkende ise, butonumuzun iki eksendeki koordinatlarını kontrol edeceğiz.Altıncı ve yedinci satırlarda, float türünde değişkenler oluşturuyoruz.Bu değişkenleri, joystick elemanımızın x ve y eksenindeki merkez noktayı hesaplamak için kullanacağız.
Arkaplan = GameObject.FindWithTag ("arkaplan").GetComponent<Image> (); Buton = GameObject.FindWithTag ("buton").GetComponent<Image>(); ButonCapi = 6;
Şimdi start() fonksiyonumuzun içerisine bu kodları yazıyoruz.İlk satırda değişkenimize etiket “arkaplan” olan arayüz elemanının, Image bileşenini eşitliyoruz.Yine ikinci satırda, etiketi “buton” olan arayüz elemanının Image bileşenini değişkenimize eşitliyoruz.Son satırda ise, int türündeki değişkenimize bir değer atıyoruz.Hatırlarsanız bu değişken joystick butonumuzun yarı çapını belirleyecekti.
Joystick üzerinde gerçekleşecek olayları belirleyelim.
public void OnDrag(PointerEventData joystick) {} public void OnPointerDown(PointerEventData joystick) {} public void OnPointerUp(PointerEventData joystick) {}
Şimdi yeni üç adet fonksiyon oluşturuyoruz.Script dosyamıza kod yazamaya başlamadan önce gerekli kütüphaneleri eklemiştik.Bu sayede yukarıda bulunan fonksiyonlarımızı, script dosyamızda kullanabilir hale geliyoruz.İlk satırdaki fonksiyon ile, joystick butonumuzun sürükleme hareketini kontrol edeceğiz.İkinci satırdaki fonksiyon ile, joystick butonumuza dokunduğumuz zamanki geri bildirimi kontrol edeceğiz.
Son satırdaki fonksiyon ile de, bu butondan elimizi çektiğimiz zamanki geri bildirimi kontrol edeceğiz.Tabi bu fonksiyonlarda bir parametre kullanmamız gerekiyor.Yoksa veri alışverişini sağlayamayız.Burada PointerEventData kodu ile bu bildirimi sağlıyoruz.
KoordinatXY = Vector2.zero;
Şimdi ilk fonksiyonumuz olan OnDrag içerisine bu kodu yazıyoruz.Bu kod ile Vector2 değişkenmizin koordinatlarını sıfıra “0” eşitliyoruz.Bunu “new Vector2(0,0,0)” şeklinde de yazabilirdik.
if(RectTransformUtility.ScreenPointToLocalPointInRectangle (Arkaplan.rectTransform, joystick.position, joystick.pressEventCamera, out KoordinatXY)) {}
Daha sonra yeni bir koşul oluşturuyoruz.Koşulumuzda ilk olarak RectTransformUtility sınıfını yazıyoruz.Bu sınıf ile elemanlarımızın Transform bileşenlerine erişebileceğiz.Daha sonra ScreenPointToLocalPointInRectangle fonksiyonu ile ekranımızda yer alan joystick elemanlarını pozisyonlarını, local yani yerel alandaki pozisyonlara dönüştürüyoruz.Tabi burada da bitmedi.
Bu fonksiyonun parametrelerini girmemiz gerekiyor.İlk olarak, arkaplan elemanımızın sahnedeki pozisyonunu ekliyoruz.Daha sonra fonksiyonumuzda belirlediğimiz “joystick” parametresinin pozisyonunu ekliyoruz.Üçüncü parametremiz olarak, bu parametrenin ekli olduğu kamerayı çekiyoruz.Sahnemizde bir tek Main.Camera olduğu için, burada bahsedilen kamera o nesne oluyor.Son olarak ise, Vector2 değişkenimizi ekliyoruz.Çıktıyı bu değişken kontrol edecek.Buraya kadar herhangi bir koşuldan bahsetmedik.Çünkü RectTransformUtility, bir bool değişkeni görevi görür.Eğer koordinatlarda bir isabet varsa, true değerini döndürür.
KoordinatXY.x = (KoordinatXY.x / Arkaplan.rectTransform.sizeDelta.x); KoordinatXY.y = (KoordinatXY.y / Arkaplan.rectTransform.sizeDelta.y); if (Arkaplan.rectTransform.pivot.x == 1) { xEkseni = KoordinatXY.x * 2 + 1; }else{ xEkseni = KoordinatXY.x * 2 - 1; } if (Arkaplan.rectTransform.pivot.y == 1) { yEkseni = KoordinatXY.y * 2 + 1; }else{ yEkseni = KoordinatXY.y * 2 - 1; }
Bu koşulun içerisinden devam ediyoruz.İlk ve ikinci satırlarda, Vector2 değişkenimizin x ve y eksenleri için sınırlar belirliyoruz.İlk satıra bakacak olursak değişkenimizi, arkaplan için oluşturduğumuz UI elemanının x eksenindeki boyutuna bölüyoruz.İkinci satırda da aynı işlemi y ekseni için tekrarlıyoruz.Üçüncü satırda ise yeni bir koşul oluşturuyoruz.Burada eğer arkaplan elemanımızın x eksenindeki merkezi, bire “1” eşitse koşulumuz doğru oluyor.Dördüncü satırda koşulumuzun doğru olması durumunda değişkenimizi, iki ile çarpıp bir ekliyoruz.
Aksi bir durumda ise, yine aynı işlemi yapıyoruz fakat bu sefer bir çıkartıyoruz.Y ekseni için oluşturduğumuz ikinci koşula bakacak olursak, yine aynı işlemler geçerli.Tek farkı x ekseni yerine y ekseni için işlem yapıyor olmamızdır.Buradaki işlemler ne diye soracak olursanız, joystick butonumuz için Vector2 koordinatlarında pozisyon belirliyoruz.
KoordinatXYZ = new Vector3 (xEkseni, 0, yEkseni); if (KoordinatXYZ.magnitude > 1f) { KoordinatXYZ = KoordinatXYZ.normalized; } else { KoordinatXYZ = KoordinatXYZ; }
Az önce Vector2 için işlemler gerçekleştirmiştik.Şimdi ise, Vector3 için oluşturduğumuz değişken üzerinde bir takım işlemler gerçekleştireceğiz.İlk satırda, değişkenimiz için yeni bir koordinat oluşturuyoruz.Burada y eksenini sıfır “0” olarak belirliyoruz.Çünkü joystick butonumuz üçüncü bir eksende hareket etmiyor.İkinci satırda, yeni bir koşul oluşturuyoruz.
Eğer Vector3 değişkenimizin uzunluğu, birden “1” büyük ise, koşulumuz doğru oluyor.Tabi bu denetimi, Magnitude fonksiyonu ile sağlıyoruz.Üçüncü satırda, değişkenimizi normalleştiriyoruz.Yani Normalized fonksiyonu ile çıkan sonucu, bire “1” eşitliyoruz.Beşinci satıra bakacak olursak, koşulumuzun gerçekleşmemesi durumunda değişkenimizi kendisine eşitliyoruz.
Butonumuzun hareket edeceği alanı belirleyelim.
Evet buraya kadar, Vector2 ve Vector3 koordinatlarındaki hareketleri bir takım işlemlerden geçirerek, joystick elemanlarımızın sınırlarını belirledik.Şimdi ise, elde ettiğimiz sonuçları kullanarak joystick butonumuzu harekete geçirelim.
Buton.rectTransform.anchoredPosition = new Vector3 (KoordinatXYZ.x * (Arkaplan.rectTransform.sizeDelta.x / ButonCapi), KoordinatXYZ.z * (Arkaplan.rectTransform.sizeDelta.y / ButonCapi));
Yine aynı fonksiyonun içerisinden devam ediyoruz.Buton elemanımızın, anchors yani çapa pozisyonları için yeni değerleri oluşturuyoruz.Tabi yeni pozisyonları Vector2 olarak yani x ve y eksenlerindeki değerleri kullanarak oluşturuyoruz.Burada yaptığımız işlem, arkaplan resmimizin x eksenindeki boyutu, butonumuzun yarıçapı için oluşturduğumuz değişkene bölmek ve çıkan sonucu, Vector3 değişkenimizin x değeri ile çarpmaktır.Bu bize joystick butonumuzun içeride hareket edebileceği bir alan oluşturuyor.Aynı işlemi Vector3 değişkenimizin z ekseni içinde yapıyoruz.Buradaki “ButonCapi” değişkenimizin değerini ne kadar büyütürseniz, butonumuzun hareket sınırı o kadar geniş olacaktır.
OnDrag (joystick);
Evet şimdi OnPointerDown fonksiyonumuzun içerisine bu kodu yazıyoruz.Burada, joystick butonumuza bastığımız zaman ilk oluşturduğumuz fonksiyonu çağırıyoruz.Böylece parametre aracılığı ile iki fonksiyon arasında bir veri alışverişi oluyor.
KoordinatXYZ = Vector3.zero; Buton.rectTransform.anchoredPosition = Vector3.zero;
Şimdi ise üçüncü fonksiyonumuz olan yani, OnPointerUp fonksiyonu içerisine bu kodları yazıyoruz.Bu fonksiyonu joystick butonumuz ile teması kesince oluşacak olaylar için yazmıştık.Yani elimizi butondan çekersek ne olacağını kodluyoruz.İlk satırda, Vector3 değişkenimizin koordinatlarını sıfıra “0” eşitliyoruz.İkinci satırda ise, buton elemanımızın çapa pozisyonlarını sıfıra eşitliyoruz.
Camera.main.backgroundColor = new Color(KoordinatXYZ.x, KoordinatXY.y, KoordinatXYZ.z, 1f);
Hatırlarsanız sahnemizi oluşturken, ana kameramızın Clear Flags özelliğini, “Solid Color” moduna getirmiştik.Böylece ekranımız tek bir renkten oluşuyordu.İşte bu rengi joystick butonumuz ile değiştirmek için update() fonksiyonumuzun içerisine bu kodu yazıyoruz.Burada yeni bir renk oluştruyoruz ve parantez içerisinde RGB paleti için, farklı eksenler belirtiyoruz.Böylece butonumuzun hareket ettiği eksene göre, arkaplan rengimiz değişiyor.Bunu sahnemiz boş kalmasın diye son anda ekledim.Yazmanız şart değil.Evet bu kodumuz ile, script dosyamızı tamamlamış oluyoruz.
Evet son olarak Project penceresinde bulunan bu C# Script dosyamızı sürükleyerek, Canvas nesnemizin üzerine bırakıyoruz.Artık projemiz tamamlanmış oldu.Bir sonraki yazıda görüşmek üzere…