UNITY 3D Multi-Touch Destekleyen Butonlar Oluşturmak

Yayınlandı: 01 Ağustos 2014 yasirkula tarafından Oyun Tasarımı, UNITY 3D içinde

NOT: Unity’nin yeni UI sistemi otomatik olarak multi-touch desteklediği ve OnGUI‘ye göre daha performanslı çalıştığı için, artık OnGUI veya GUI Texture kullanmak yerine UI sistemini kullanmanızı öneririm.

Hepinize merhaba,

Unity’nin OnGUI fonksiyonuyla oluşturulan arayüz elemanları (butonlar, sliderlar vb.) ve GUI Texture‘larla oluşturulan butonlar multi-touch desteklemez. Yani diyelim ekranda iki buton varsa, bu ikisine aynı anda basamazsınız çünkü ekranda birden çok parmak olduğunda GUI elemanları düzgün çalışmazlar. Örneğin araba oyunlarında direksiyonu tutarken bir yandan da gaza basabilmek için butonlarınızın multi-touch desteklemesi gereklidir.

Bir arayüz elemanının multi-touch desteklemesi, ekrandaki parmak sayısını döndüren Input.touchCount değişkenini ve bir parmak hakkında detaylı bilgi döndüren Input.GetTouch fonksiyonunu kullanmasıyla sağlanır. Bu fonksiyon hakkında daha fazla bilgi için: https://yasirkula.com/2013/07/17/unity-ile-androide-uygulama-gelistirmek-1-dokunmatik-ekran-entegrasyonu/

A) GUI Texture İle Oluşturulan Butonlar

Elimizde public GUITexture buton; diye bir değişken olsun ve bu değişkene multi-touch desteklemesini istediğimiz GUI Texture objesi değer olarak verilmiş olsun.

Eğer GUI Texture’a dokunulduğu anda bir kodun tek seferlik çalışmasını istiyorsanız şu scripti kullanın:

public GUITexture buton;

void Update()
{
	for( int i = 0; i < Input.touchCount; i++ )
	{
		Touch t = Input.GetTouch( i );
		if( t.phase == TouchPhase.Began && buton.HitTest( t.position ) )
		{
			// yapılacaklar buraya
		}
	}
}

Buradaki GUITexture.HitTest fonksiyonu, parmağın ekrandaki konumu o GUITexture’un içerisindeyse (yani parmak GUITexture’a dokunuyorsa) true döndürür, yoksa false döndürür.

Eğer parmak GUI Texture’nin üzerinde olduğu sürece bir kodun çalışmasını istiyorsanız (mesela gaz pedalına dokunmak) şu scripti kullanın:

public GUITexture buton;

void Update()
{
	for( int i = 0; i < Input.touchCount; i++ )
	{
		Touch t = Input.GetTouch( i );
		if( buton.HitTest( t.position ) )
		{
			// yapılacaklar buraya
		}
	}
}

B) OnGUI Fonksiyonunda Oluşturulan Butonlar

İki çeşit GUI butonu bulunmakta: GUI.Button ve GUI.RepeatButton. İlki butona basıldığı anda tek seferlik çalışırken ikincisi butona basılı tutulduğu sürece sürekli çalışır.

Diyelim ki oyunumuzda ekranda iki buton var: gaz butonu (RepeatButton) ve kameranın açısını değiştirmeye yarayan bir buton (Button). Normalde bu iki butonu şöyle oluştururuz (bu, multi-touch desteklemeyen koddur):

void OnGUI()
{
	if( GUI.Button( new Rect( 0, 0, 200, 100 ), "Kamera Açısı" ) )
	{
		// kamera açısını değiştirmeye yarayan kod
	}

	if( GUI.RepeatButton( new Rect( 0, 150, 200, 100 ), "GAZ" ) )
	{
		// gaza basılı tutulurken yapılacak şeyler
	}
}

Bu kodu şöyle değiştirerek multi-touch desteği verebilirsiniz:

private Rect kameraButonRect;
private Rect gazButonRect;

void Start()
{
	kameraButonRect = new Rect( 0, 0, 200, 100 );
	gazButonRect = new Rect( 0, 150, 200, 100 );
}

void Update()
{
	for( int i = 0; i < Input.touchCount; i++ )
	{
		Touch t = Input.GetTouch( i );
		Vector2 parmakKonum = new Vector2( t.position.x, Screen.height - t.position.y );

		if( t.phase == TouchPhase.Began && kameraButonRect.Contains( parmakKonum ) )
		{
			// kamera açısını değiştirmeye yarayan kod
		}
		else if( gazButonRect.Contains( parmakKonum ) )
		{
			// gaza basılı tutulurken yapılacak şeyler
		}
	}
}

void OnGUI()
{
	GUI.Button( kameraButonRect, "Kamera Açısı" );
	GUI.RepeatButton( gazButonRect, "GAZ" );
}

GUITexture.HitTest‘e benzer şekilde, buradaki Rect.Contains fonksiyonu, parmağın ekrandaki konumu o butonun içerisindeyse true döndürür, yoksa false döndürür.

Bu kısa dersin sonuna geldik. Sonraki derslerde görüşmek üzere!

yorum
  1. LS dedi ki:

    Merhaba hocam. 2 butonum var biriyle sayı artırıyorum diğeri ile azaltıyorum fakat azaltma ve artma işlemi birbirinden bağımsız oluyor. 15’de iken azaltma -1’den devam ediyor. Sorunum nedir acaba? Son olarak bu durumu çözersem, istediğim sayıya geldiğinde tetikleme nasıl yapabilirim? text ile int olunca if konusunda sanırım çevirme yapmam gerekiyor.

    public Text numberText;

    public int number = 0;

    public void ButtonClickedPlus()

    {

    number++;

    numberText.text = number.ToString();

    }

    public void ButtonClickedMinus()

    {

    number–;

    numberText.text = number.ToString();

    }

    • yasirkula dedi ki:

      Verdiğiniz kodda hiçbir sıkıntı yok. Bence ButtonClickedMinus’a Debug.Log koyup butona tıklayınca fonksiyonun kaç defa çağrıldığına bakın. Ayrıca log’unuzda önce number’ın önceki değerini, sonra da yeni değerini bastırın. “number–” satırının sayıyı 15’ten -1’e düşürmesi imkansız o yüzden hata başka bir yerle bağlantılı çıkacak. İstediğiniz sayıya geldiğinizi, ButtonClickedPlus ve ButtonClickedMinus fonksiyonlarında number’ı if’in içine sokarak kontrol edebilirsiniz.

      • LS dedi ki:

        Çok teşekkür ederim çalıştı. 2den fazla (+ -)li butonum var. Bunlardan belirli değerlere geldiğinde tetiklemek istedim fakat çalışmadı. Sanırım hatalarım var. Update fonksiyonu içinde butonların Minus ve Plus fonksiyonlarını çektim. onun içinde if(sayi1==5 && sayi2==7 && sayi3==8) olduğunda setActive(true) gibi değerler koydum çalışıyorsa objemi göreyim diye çalışmadı.

        Bu hatayı veriyor:NullReferenceException: Object reference not set to an instance of an object
        ButtonIncreaseDecrease.LecithinButtonPlus () (at Assets/ButtonIncreaseDecrease.cs:99)
        ButtonIncreaseDecrease.Update () (at Assets/ButtonIncreaseDecrease.cs:37)

      • yasirkula dedi ki:

        NullReferenceException, erişmeye çalıştığınız bir objenin değeri atanmamışsa ortaya çıkar. Örneğin GetComponent null döndürürse (component yok anlamına gelir) veya public değişkene değeri atanmadıysa.

      • LS dedi ki:

        Debug.Log ile baktığımda hocam butondan girdiğim değerlerin if bloğunda karşılıklı olarak birbirini tanımadığını gördüm. && işleminde çalışması lazımken çalışmıyordu. Farklı butonlardan çektiğim değerleri if ile nasıl karşılaştırabilirim?

      • yasirkula dedi ki:

        Birden çok koşulu && ile kontrol edebilirsiniz. Tam dediğinizi anlamadım :}

      • LS dedi ki:

        teşekkür ederim hocam siz yönlendirdekten, sonra çalıştırmaya devam ediyorum. Son sorum kaldı, şimdi 4-5 butonum vardı. Bunlarla belirli değerler girip, if ile sistemimi o değerlere geldiğinde çalıştırıyorum. Şimdi o değerlere gelse bile çalışmasın, kontrol butonuna bastığımda çalışsın(4 butonu kontrol edip) ya da hata mesajı versin istiyorum. Bunu nasıl yapabilirim?

      • yasirkula dedi ki:

        “if(sayi1==5 && sayi2==7 && sayi3==8)” kodunuzu sadece “public void KontrolEt()” fonksiyonuna yazıp kontrol butonuna basınca bu fonksiyonu çalıştırabilirsiniz.

      • Ls dedi ki:

        teşekkürler hocam son aşamada sistem kitleniyor bitirmek üzereyim projemin bir kısmını sayenizde. Sayılarımı sınırlandırmam gerekiyor 0 ile 10 arasında diyelim. Sistem çalışıyor düzenli artma azaltma oluyor butonlarla, sonra 10 ya da 0a geldiğinde sistem kitleniyor. Artma azalma daha olmuyor. Çok ilginç geldi..

        public void ButtonPlus()
        {

        if(0<=test && test<=10)
        {
        test++;
        testText.text = sugar.ToString();

        }

        }

      • yasirkula dedi ki:

        Fonksiyonun içeriğini şöyle yapmanızı öneririm:

        test = Mathf.Clamp(test + 1, 0, 10);
        testText.text = sugar.ToString();

      • LS dedi ki:

        Valla çalıştı. :)) Proje bitiminde size bir öğrenci olarak hediye yollamak isterim hocam. 🙂 nerede çalışıyorsunuz bilmiyorum ama insanlara çok yardımcı oluyorsunuz.

      • yasirkula dedi ki:

        Düşündüğünüz için teşekkür ederim. İyi dilekleriniz benim için yeterli 🎁

      • LS dedi ki:

        Merhaba hocam. Daha önce bu bug başınıza geldi mi acaba? Butonlar ile 0 ile 1 arasına geldiğimde bu değeri 1,490116E-08 veriyor. Kod bloğum böyle.

        if (0f <= denemeTest && denemeTest <= 0.5f)
        {
        denemeTest = Mathf.Clamp(denemeTest + 0.1f, 0.0f, 0.5f);
        denemeTest Text.text = denemeTest .ToString();

        }

      • LS dedi ki:

        hocam böyle bugı durdurdum. Umarım sistemi zorlayan bir kod eklememişimdir. 🙂
        denemeTest = (float)System.Math.Round(denemeTest , 2);

      • yasirkula dedi ki:

        Kodu her frame binlerce kez çalıştırmadığınız sürece zorlamaz. Bu sıkıntının teknik sebebi “floating point precision”. Özellikle bu yüzden, 2 float sayının birbirine eşit olup olmadığını kontrol etmek için Mathf.Approximately fonksiyonu mevcut.

  2. Emirhan dedi ki:

    hocam merhabalar
    butona basılı tuttuğumda istediğim işlevi yapmasını istiyorum ancak takıldım bu konuda dersiniz varsa bulamadım yardımcı olursanız sevinirim

    • yasirkula dedi ki:

      Eğer bu dersteki koddan bahsediyorsanız, “// gaza basılı tutulurken yapılacak şeyler” yazan yere kendi kodunuzu yazabilirsiniz. UI sisteminden bahsediyorsanız, şu dersteki “Bir UI Elemanına Basılı Tutulduğu Sürece Yapılacak Şeyleri Belirlemek” kısmına bakabilirsiniz.

      • Emirhan dedi ki:

        bu dersle alakalı değildi hocam ancak çözdüm yine sizin sayenizde sayılır SimpleInput dersiniz ve ordaki kodlarınız sayesinde

  3. osman dedi ki:

    merhabalarlar
    iki kişilik bir oyunum var ve 30 button var ekranda herbirinin fonksiyonu farklı paremetre almış ben direk kodla buttona tıklatmaya çalışıyorum onu nasıl yapabilirim teşekürler

  4. Eyup dedi ki:

    Yani yazılım dışındaki bütün konuları demek istedim 😀

  5. Eyup dedi ki:

    merhabalar hocam,
    Admob ödüllü reklam izle, belirlediğim butonnun (interactable’ı) açılsın.

    Hocam ben sadece projeleri satın alıp yayınlıyorum. Yani mantigi kolay olsa bile bunu yazabilecek bilgiye sahip değilim. Yazılım konusunda herşeyi yapabiliyorum :’)
    Admob rewarded hazır buton a tıklandığında ödüllü reklam çıkıyor. Mesela bir buton’a tıklandığında, başka bir butonun açılmasını istiyorum. Hocam varsa zamanınız bu kodu yazabilir misiniz ♥
    Eğer admob ödüllü reklam scripti lazim ise hemen dönüş yaparım. eyupbatmaz39@gmail.com

    Bu arada içerikleriniz çok iyi hocam tekrardan teşekkürler!

    • yasirkula dedi ki:

      buton1.onClick.AddListener(() =>
      {
      // Butonun açılmasından kastınız alttaki kodlardan hangisi ise, onun comment’ini kaldırırsınız
      //buton2.interactable = true;
      //buton2.enabled = true;
      //buton2.gameObject.SetActive(true);
      } );

      Ayrıca butonun On Click’ine Inspector’dan değer vererek de, kod yazmadan bunu başarabilirsiniz.

  6. osman cvz dedi ki:

    Selamlar butona bastığımda kod yardımıyla butonun bi miktar inip tekrar yükselmesini istiyorum bu sayede basma efekti vericem ama animasyon kullanmak istemiyorum.nedir bunun kodu ?

  7. Alp Can Marangoz dedi ki:

    Abi Ellerine sağlık ancak sürekli parmağımı kaydırmak zorunda kalıyorum,basılı tutunca harekete devam etmiyor. Başka bir projede denedim.

Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.