UNITY İle Android’e Uygulama Geliştirmek – 2 – Telefon Sensörünü Kullanmak

Yayınlandı: 22 Temmuz 2013 yasirkula tarafından Oyun Tasarımı, UNITY 3D içinde

GÜNCELLEME (01.07.2018): Kod C#’a çevrildi.

Tekrar merhaba,

Bu derste, Android veya iOS için uygulama geliştirirken telefonun sensörünü nasıl kullanabileceğinizi göreceksiniz. Bu sefer ilk derse göre daha eğlenceli bir uygulama yapmaya çalışacağız: sensörle bir topu yönettiğimiz basit ama geliştirmeye açık bir oyunun temellerini atacağız (bkz. Ballance oyunu). Dokunmatik ekranı kullanmayı anlattığım ilk derse gitmek için tıklayın: https://yasirkula.com/2013/07/17/unity-ile-androide-uygulama-gelistirmek-1-dokunmatik-ekran-entegrasyonu/

Derse başlamadan önce, Unity için Android SDK‘yı kurmuş olmanız lazım. Kurmadıysanız sizi buraya alalım: https://yasirkula.com/2013/07/17/unity-android-sdk-kurulumu-resimli-anlatim/

Başlayalım o halde…

Telefonun sensörüyle ilgili işimize yarayabilecek sadece 2 değişken var; bu yüzden Unity’de sensörü kullanmak, dokunmatik ekranı kullanmaya göre daha kolay. İşleyeceğimiz ilk değişken Input.deviceOrientation. Bu değişken, telefonun hangi pozisyonda tutulduğunu belirtir. Yani cihazın yere dik ve düzgün bir şekilde (HOME butonu aşağıda olacak şekilde) mi (DeviceOrientation.Portrait), yere dik ama tepetaklak bir şekilde (HOME butonu yukarıda olacak şekilde) mi (DeviceOrientation.PortraitUpsideDown), yere dik ve sola yatırılmış bir şekilde mi (DeviceOrientation.LandscapeLeft), yere dik ve sağa yatırılmış bir şekilde mi (DeviceOrientation.LandscapeRight), yere paralel ve ekranı yukarı bakacak şekilde mi (DeviceOrientation.FaceUp) yoksa yere paralel ve ekranı aşağı bakacak şekilde mi (DeviceOrientation.FaceDown) tutulduğunu depolar. Eğer ki cihaz abuk subuk bir eğimle tutuluyorsa o zaman bu değişken DeviceOrientation.Unknown değerini alır.

Şimdi gelelim asıl işimize yarayacak olan değişkene, yani direkt telefonun sensörünün döndürdüğü değeri okumaya yarayan değişkene: Input.acceleration. Bu değişken bir Vector3 döndürür ve bu vektörün x, y ve z değerleri, -1.0 ile 1.0 arasında birer float değer alır. Eğer ki cihazınız yere dik ve ekranı size bakacak şekilde duruyorsa, Input.acceleration değişkeninin x değeri, cihazı sağa sola yatırarak, z değeri ise cihazı ileri geri yatırarak değişir. Yok eğer cihaz yere paralel ve ekranı yukarı bakacak şekilde duruyorsa, bu sefer Input.acceleration değişkeninin x değeri yine cihazı sağa sola yatırarak değişirken y değeri cihazı aşağı yukarı yatırarak değişir. Diğer pozisyonlardan bahsetmiyorum çünkü normal bir oyunda ekran bu bahsettiğim 2 durumdan birindeyken oyun oynanır. Anlayacağınız, eğer cihazınız insancıl bir şekilde tutuluyorsa, Input.acceleration değişkeninin x değeri cihazı sağa sola yatırarak değişirken, cihazın pozisyonuna bağlı olarak y ve z değerleri ise, cihazı ileri geri ya da yukarı aşağı oynatarak değişir. Olayı en iyi şekilde anlamak için yapmanız gereken şey, bu sensör değerlerini bizzat test etmek. Bunun için yeni bir proje açın, yeni bir C# script oluşturun ve scripti ve Main Camera‘ya atın (ardından Android için Build alıp cihazı bol bol evirip çevirin):

void OnGUI()
{
	string yazi = "Input.acceleration: " + Input.acceleration;
	yazi += "\nInput.deviceOrientation: " + Input.deviceOrientation;
	yazi += "\nScreen.orientation: " + Screen.orientation;
	
	GUI.Label( new Rect( 0, 0, Screen.width, Screen.height ), yazi );
}

Artık hazırsanız oyunumuzu yapmaya başlayabiliriz!

Yeni açtığınız projede yeni bir Sphere GameObject oluşturun. Buna Rigidbody ekleyin ve “Drag” değerini 3 yapın (objenin hava sürtünmesi ile kendiliğinden durabilmesi için). Bu obje topumuz olacak. Ardından topun üstünde yürümesi için bir Cube GameObject oluşturup bunu büyültün ve topun aşağısına zemin niyetine koyun. Buna ek olarak, birkaç Cube GameObject daha oluşturun ve bunları sahnede rastgele konumlandırın. Bu küp objeler topumuz için birer engel olacaklar. Kendileri için hiçbir kod gerekmiyor, Collider‘ları olması yeterli. Son olarak, sahneye bir de Directional Light ekleyin. Benim hazırladığım sahneden bir görüntü:

1

Şimdi kamerayı ayarlayalım. Topun ve kameranın Rotation‘ını sıfırlayın. Ardından kamerayı, z ekseninde topun biraz gerisinde ve y ekseninde topun biraz yukarısında olacak şekilde konumlandırın. Dilerseniz kamerayı aşağı yönde biraz döndürebilirsiniz. Şimdi bir Empty GameObject oluşturup bunu top objesinin bir child objesi yapın ve Transform‘unu resetleyin. Ardından kamerayı da bu Empty GameObject‘in child objesi yapın. Son olarak da Empty GameObject‘e aşağıdaki ufak scripti yazın:

void Update() 
{
	transform.eulerAngles = Vector3.zero;
}

Niçin böyle yaptık? Çünkü top hareket ettiğinde kendi etrafında dönecek ve direkt kamerayı topun child objesi yapsaydık, o da topla beraber dönecekti. Ama şimdi Empty GameObject sayesinde kamera topu takip ediyor ama topla birlikte dönmüyor çünkü Empty GameObject‘in eğimini sürekli (0,0,0)‘a ayarlıyoruz. (Eğer dilerseniz sahnedeki objelere renkli basit materyaller ekleyerek sahneyi güzelleştirebilirsiniz.)

Artık tek yapmamız gereken, topa bir hareket script’i yazmak. Bunun için yeni bir C# script oluşturup bunu top objesine atayın ve içini şu şekilde değiştirin:

Rigidbody rb;

void Start()
{
	rb = GetComponent<Rigidbody>();
}

void FixedUpdate()
{
	rb.AddForce( new Vector3( Input.GetAxis( "Horizontal" ), 0, Input.GetAxis( "Vertical" ) ) * 10 );
	rb.AddForce( new Vector3( Input.acceleration.x, 0, -Input.acceleration.z ) * 30 );
}

Bu kod sayesinde, oyunu hem PC’de hem de Android’de test edebilirsiniz. Gördüğünüz üzere, topu sola hareket ettirmek için cihazı sola yatırıp Input.acceleration.x‘ini negatif bir değer yapmalı, ya da ileri hareket ettirmek için cihazı ileri yatırıp Input.acceleration.z değerini negatif (haliyle –Input.acceleration.z değerini pozitif) yapmalıyız. Fark edeceğiniz üzere, cihazı ileri geri yatırarak Input.acceleration‘ın z değeriyle oynuyoruz, yani oyunumuzun düzgün oynanabilmesi için cihazın kusursuz bir şekilde yere dik ve ekranı bize bakacak şekilde durması gerekiyor. Bu da pek iyi bir şey değil. Kullanıcı belki de oyunu ekran 45 derece açıyla yukarı bakıyorken oynamak isteyecek. Bu sorunu çözmek için script’i biraz daha geliştirelim. Ama ondan önce dilerseniz oyunu PC’de ve Android cihazınızda test edin. İşiniz bitince kodu şununla değiştirin:

Rigidbody rb;
Vector3 ilkPozisyon;

void Start()
{
	ilkPozisyon = Input.acceleration;
	rb = GetComponent<Rigidbody>();
}

void FixedUpdate()
{
	rb.AddForce( new Vector3( Input.GetAxis( "Horizontal" ), 0, Input.GetAxis( "Vertical" ) ) * 10 );
	rb.AddForce( new Vector3( Input.acceleration.x - ilkPozisyon.x, 0, -Input.acceleration.z + ilkPozisyon.z ) * 30 );
}

Gördüğünüz gibi, çok basit bir hamleyle sorunu çözdük: oyun başlarken cihazın sensör değerlerini ilkPozisyon değişkenine kopyalıyoruz ve daha sonra FixedUpdate()‘te yaptığımız sensöre dayalı işlemi, (0,0,0)‘ı referans alarak değil de bu değişkenin değerini referans alarak yapıyoruz. Yalnız eğer Unity 4.2’den eski bir versiyon kullanıyorsanız sıkıntı yaşamanız mümkün çünkü bu versiyonlarda, bir bug’dan dolayı oyun Android’de 5 saniye gecikmeli olarak açılıyor. Bu esnada ekran siyah oluyor ancak arkaplanda oyun oynamakta oluyor. Bunu çözmek için yapmanız gereken şey çok basit: Unity sürümünüzü güncelleyin.

Böylece bu dersin de sonuna geldik. Elimizde çok basit bir oyunun prototipi bulunmakta ve biraz hayal gücüyle çok güzel bir oyun ortaya çıkabilir. Kendinizi geliştirmek amacıyla oyuna parmak sürükleme desteği de sunmaya çalışın. Böylece topu ekranda parmağımızı sürükleyerek de hareket ettirebilelim.

Umarım faydalı olmuştur, başka derslerde görüşmek üzere!

yorum
  1. ibrahim altun dedi ki:

    iyigunler hocam ilk pozisyon belirtilen script benim oyunumda basarılı olmadı oyuna ilk giriste mukemmel calısıyor öldugumde scene tekrarlandıgında saga veya sola cekiyor diger pozunson belirtmeden olan scripti yazdım oda saga cekiyor bunu nasıl cozebilirim tesekkurler

    • yasirkula dedi ki:

      static bool init = false; değişkeni ekleyin ve Start’ı şöyle değiştirin:

      void Start()
      {
      if( !init )
      {
      ilkPozisyon = Input.acceleration;
      init = true;
      }

      rb = GetComponent();
      }

  2. ibrahim altun dedi ki:

    hocam iyigunler hocam konudan alakasız bir soru socucamda google play için anahtar kelime nasıl eklenir aso nasıl yapılır web de uzun suredir aramama ragmen bir kaynak bulamadım onerebiliceginiz bir kaynak varmıdır ve hocam misal rıse up gibi olan bir uygulamada 1. level 2. level vs hepsi bir biriyle yer degistiriyor bunu oyunumuza nasıl uyguluyabiliriz bununla ilgili bilginiz varmı acaba yardımlarınız ıcın cok tesekkur ederim

    • yasirkula dedi ki:

      ASO veya SEO konularında maalesef bilgim yok, şimdiye kadar hep oyunla alakalı popüler kelimeleri oyunun açıklamasında kullanmak şeklinde öneriler okudum. Rise Up oyununda gördüğüm kadarıyla her level bir prefab yapılmış ve balon bir level’ın içine girdiğinde, sonraki level mevcut level’ın yukarısında Instantiate ediliyor.

  3. ibrahim altun dedi ki:

    hocam misal trafic racer ı dusunun ekranı saga sola cevirdiginizde araba saga veya sola gidiyor ama araba takla acmıyor sadece posisyonu degisiyor bende 2d bir oyun yapıyorum verdiginiz scripti kendi oyunuma yapıstırdım ben objemin ekranı cevirdigimde rotasyonunun degismemesini sadece posisyonunun degismesini istiyorum misal su an hocam ekranı saga kırdım objem top gibi hem saga donuyor hem saga gidiyor ben objemin kendi ekseninde donmemesını ıstıyorum yardımlarınız ıcın tesekkur ederim

    • yasirkula dedi ki:

      Objenin Rigidbody’sindeki Constraints’in Rotation Z değerini işaretlemeyi deneyebilirsiniz. Gerekirse diğer Rotation’ları da tek tek işaretlemeyi deneyebilirsiniz. Belki Traffic Racer’da sağa sola direkt transform.Translate ile gidiliyor da olabilir, yani rb.AddForce harici çözümler de deneyebilirsiniz.

  4. ibrahim altun dedi ki:

    hocam merhaba ben oyunumda dondurmeyi sadece position da yapmak istiyorum ve dondurmeyi hassasiyetini nasıl ayarlıyabilirim bide telin sol ust tarafında yazılar cıkoy dondurmeyle ilgili onları nasıl kaldırabilirim tesekkurler

    • yasirkula dedi ki:

      Döndürmeyi sadece position’da yapmayı anlayamadım. Telefonu sağa-sola hareket ettirdikçe bir şey olmasını istiyorsanız, bildiğim kadarıyla bu mümkün değil. Sadece telefonu sağa sola çevirince bunu algılamak mümkün. Döndürme hassasiyetini ayarlamak için, Input.acceleration’ın değerini istediğiniz sayı ile çarpabilirsiniz. Yazıları silmek için de OnGUI fonksiyonunu script’inizden silebilirsiniz.

  5. Alper dedi ki:

    Androide bir hayatta kalma oyunu yapıyorum elimde silah var silah ateş ediyor reloadı androide yaptığım için farklı bir butona yapmak zorundayım silahın ateşi için diğer scripteki kodlara ulaşıyorum reload scriptinde işlemleri yazıyorum ama oyunu çalıştırınca

    NullReferenceException: Object reference not set to an instance of an object
    Reload.Reload_Click() (at assets/kodlar/Reload.cs:21) diye bir hata oluyor reload butonu yapmam için lütfen bana yardımcı olur

    • yasirkula dedi ki:

      Reload script’inizin 21. satırındaki bir objenin değeri yok hatası alıyorsunuz. Inspector’dan, değişkenin değerini alıp almadığını kontrol edebilirsiniz. Eğer değişkenin değeri null ise, GameObject.Find ve/veya GetComponent gibi fonksiyonlarla değişkene değer atamayı deneyebilirsiniz.

      • Alper dedi ki:

        ateş etme butonuna basınca silah tek tek ateş ediyor basılı tutunca sürekli ateş etmesini nasıl sağlayabilirim bu arada cevabınız için teşekkürler 🙂

      • yasirkula dedi ki:

        Şuna benzer bir kod kullanabilirsiniz:

        public float ikiAtesArasiBekleme = 0.1f; // Saniyede 10 kurşun
        private float sonrakiAtesZamani;
        
        void Update()
        {
        	if( Input.GetMouseButton( 0 ) )
        	{
        		float zaman = Time.realtimeSinceStartup;
        		
        		if( Input.GetMouseButtonDown( 0 ) )
        			sonrakiAtesZamani = zaman;
        		
        		while( zaman >= sonrakiAtesZamani )
        		{
        			// Buraya ateş etme kodunuzu girin
        			
        			sonrakiAtesZamani += ikiAtesArasiBekleme;
        		}
        	}
        }
        

Cevap Yazın

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.