Unity 3D Coroutine’ler

Yayınlandı: 20 Kasım 2018 yasirkula tarafından Oyun Tasarımı, UNITY 3D içinde

Hepinize merhabalar,

Bu derste, Unity‘nin popüler ve bir o kadar da güçlü bir özelliği olan coroutine‘lerden bahsedeceğiz. Coroutine’ler vasıtasıyla örneğin bir kodun çalışmasını birkaç saniye geciktirebilir, belli bir işlemin bitmesini bekleyebilir veya işlemi birkaç saniyeye yayabilirsiniz (bir objeyi bir yerden başka bir yere 2 saniyede hareket ettirmek gibi).

Hazırsanız derse başlayalım!

Coroutine’ler de aslında birer fonksiyondurlar ve birkaç ufak fark haricinde, aşina olduğunuz normal fonksiyonlardan bir farkları yoktur:

  1. coroutine’ler IEnumerator döndürmelidir. Bu arayüze erişebilmek için kodunuzun başına using System.Collections; satırını eklemeniz gerekir. Ama belki fark ettiğiniz üzere, yeni oluşturulan script’lere Unity otomatik olarak bu satırı ekler çünkü coroutine’ler Unity’de sıklıkla kullanılmaktadır
  2. coroutine’ler StartCoroutine fonksiyonu ile çağrılmalıdır (aksi taktirde coroutine çalışmayacaktır)
  3. coroutine’in içinde en az bir yield return ifadesi kullanılmalıdır

Örneğin alttaki koda bir göz atalım:

void Start()
{
	Debug.Log( "Start başlangıç" );
	StartCoroutine( CoroutineTest() ); // CoroutineTest coroutine'ini başlat
	Debug.Log( "Start bitiş" );
}

IEnumerator CoroutineTest()
{
	Debug.Log( "İlk frame" );
	yield return null; // 1 frame bekle
	Debug.Log( "İkinci frame" );
}

Tahmin edeceğiniz üzere, bu koddaki coroutine’imiz CoroutineTest fonksiyonu. Bu coroutine içerisine yazdığımız yield return null; satırı, coroutine’in orada 1 frame beklemesini sağlar. Coroutine’ler, onları çağıran fonksiyonlardan bağımsız olarak hareket eder. Yani bizim CoroutineTest fonksiyonunu 1 frame bekletmemiz, Start fonksiyonunu da 1 frame bekletiyor olmamız anlamına gelmez. CoroutineTest 1 frame beklerken, Start normal seyrinde çalışmaya devam eder. Bu yüzden de bu programın çıktısı şöyle olur:

Start başlangıç
İlk frame
Start bitiş
İkinci frame

Şimdi bir de şu coroutine’e göz atalım:

IEnumerator CoroutineTest()
{
	Debug.Log( "Zaman: " + Time.time );
	yield return new WaitForSeconds( 1.5f ); // 1.5 saniye bekle
	Debug.Log( "Zaman: " + Time.time );
}

Gördüğünüz üzere, WaitForSeconds fonksiyonu vasıtasıyla bir coroutine’i belli bir süre boyunca bekletebilirsiniz. Burada dikkat etmeniz gereken nokta, bu sürenin Time.timeScale’e bağlı olmasıdır. Yani eğer timeScale’i 0.5 yaparak oyunu yavaş çekime aldıysanız, bu kod 1.5 saniye değil de 3 saniye bekler. Eğer timeScale’den bağımsız bir şekilde birkaç saniye beklemek isterseniz, WaitForSecondsRealtime fonksiyonunu kullanabilirsiniz.

Aşağıdaki örnekte ise, WWW sınıfını kullanarak internetten nasıl resim indirip bu resmi, script’in atandığı objenin materyaline atayabileceğinizi görüyorsunuz. Ayrıca bir coroutine’in parametre de alabileceğini görmüş oluyorsunuz. Bir WWW objesini yield return yaparsanız, kodunuz o WWW işleminin bitmesini bekler (bu örnekte, resmin internetten inmesini). Koddaki using ibaresinin coroutine’ler ile bir alakası olmadığı için ona çok takılmayın.

void Start()
{
	StartCoroutine( ResimIndir( "http://flags.fmcdn.net/data/flags/w580/tr.png" ) ); // ResimIndir coroutine'ini, girilen parametre ile başlat
}
 
IEnumerator ResimIndir( string url )
{
	using( WWW www = new WWW( url ) ) // WWW bir IDisposable obje olduğu için using kullanıyoruz, yani bunun coroutine'lerle bir alakası yok
	{
		yield return www; // Resmin inmesini bekle
		
		if( !string.IsNullOrEmpty( www.error ) ) // Resmi indirirken bir hata alıp almadığımıza bak
			Debug.LogError( "Bir hata oluştu: " + www.error );
		else
		{
			// Bir hata yok, resmi bu objenin materyaline texture olarak ata
			Texture2D resimTexture = www.texture;
			GetComponent<Renderer>().material.mainTexture = resimTexture;
		}
	}
}

NOT: eğer WWW yerine UnityWebRequest kullanmak isterseniz, işlemin bitmesini beklemek için UnityWebRequest objesinin Send/SendWebRequest fonksiyonunu çağırınca döndürülen objeyi yield return yapabilirsiniz.

Aşağıdaki örnek kod, kodun atandığı objeyi 3 saniyede mevcut konumundan 10,10,10 konumuna taşımaya yarar:

IEnumerator ObjeyiKimildat()
{
	float kimildamaSuresi = 3f; // Objeyi 3 saniyede hareket ettir
	float gecenSure = 0f;

	Vector3 mevcutKonum = transform.position;
	Vector3 hedefKonum = new Vector3( 10, 10, 10 );

	while( gecenSure < kimildamaSuresi ) // Henüz kimildamaSuresi kadar süre geçmediği müddetçe bu kodu çalıştır
	{
		gecenSure += Time.deltaTime; // gecenSure her saniye 1 artar
		transform.position = Vector3.Lerp( mevcutKonum, hedefKonum, gecenSure / kimildamaSuresi ); // Objenin konumunu mevcutKonum ile hedefKonum arasında oynat

		yield return null; // 1 frame bekle (yumuşak hareket için objenin konumunu bir anda değil, frame frame değiştirmeliyiz)
	}

	// kimildamaSuresi kadar süre geçti, objenin hedefKonum'a tam oturduğundan emin ol
	transform.position = hedefKonum;
}

Dilerseniz, yine StartCoroutine ile bir coroutine’in içerisinden başka bir coroutine’i başlatabilir ve bu coroutine’in bitmesini beklemek için, onu yield return yapabilirsiniz (eğer beklemek istemezseniz yield return yapmak zorunda değilsiniz):

IEnumerator CoroutineTest()
{
	Debug.Log( "Test2'yi beklemeden önce" );
	yield return StartCoroutine( CoroutineTest2() ); // CoroutineTest2 coroutine'ini başlat ve bitmesini bekle
	Debug.Log( "Test2'yi bekledikten sonra" );

	Debug.Log( "Test2'yi başlatmadan önce" );
	StartCoroutine( CoroutineTest2() ); // CoroutineTest2 coroutine'ini başlat ama bitmesini bekleme
	Debug.Log( "Test2'yi başlattıktan sonra" );
}

IEnumerator CoroutineTest2()
{
	Debug.Log( "Test2 başlangıç" );
	yield return new WaitForSecondsRealtime( 1 );
	Debug.Log( "Test2 bitiş" );
}

Peki diyelim ki çalışmakta olan bir coroutine’i durdurmak istiyorsanız napacaksınız? Burada ise StopCoroutine ve StopAllCoroutines fonksiyonları devreye giriyor. StopAllCoroutines fonksiyonu, bu objede StartCoroutine ile başlatılan tüm coroutine’leri durdurmaya yararken, StopCoroutine fonksiyonu ise, parametre olarak girilen belli bir coroutine’i durdurmaya yarar. Bunun için, durdurmak istediğiniz coroutine’i bir Coroutine değişkeninde tutmanız lazım. Örneğin:

private Coroutine donmeCoroutine;

void Update()
{
	if( Input.GetKeyDown( KeyCode.E ) ) // E tuşuna basınca
	{
		if( donmeCoroutine == null ) // Çalışmakta olan bir DondurCoroutine yok, bu coroutine'i çalıştır ve değişkene at
			donmeCoroutine = StartCoroutine( DondurCoroutine() );
		else // DondurCoroutine çalışıyor, onu durdur
		{
			StopCoroutine( donmeCoroutine );
			donmeCoroutine = null;
		}
	}
}

IEnumerator DondurCoroutine()
{
	while( true ) // Bu coroutine, durdurulmadığı sürece sürekli çalışmaya devam eder
	{
		transform.Rotate( 0, 90 * Time.deltaTime, 0 ); // Objeyi Y ekseninde döndür
		yield return null;
	}
}

Bu şekilde bu dersin sonuna geldik. Daha sonraki derslerde görüşmek üzere!

yorum
  1. Nuri dedi ki:

    Kokay gelsin. Bu WWW olayı kaldırılmış galiba? Bilginiz var mı ?

  2. Emrullah Ertaş dedi ki:

    Kaçırdığım önemli bir yorum var.

    Acaba yorum geçmişini nerden bakabilirim?

    “Nurullah Ertaş” , “Emrullah Ertaş” , “Yasin Çakıcı”

    bunların yaptıkları yorum önemliydi. nerden bakabilirim yardımcı olabilirmisiniz?

    yan tarafta yorum geçmişi bulunuyor lakin sadece 5 yorum geçmişi

    Not : 2 gün önceki yorum

  3. Arda dedi ki:

    üzgünüm buradan yazıyorum ama bir sorum daha var
    ben karakterime şöyle zıplama verdim
    if (Input.GetKeyDown(KeyCode.Space))
    {
    rb.AddForce(Vector3.up*ziplama);
    anim.speed = 1;
    anim.SetBool(“JUMP”, true);
    }
    ve bu sefer hem addforce sayesinde zıplıyor hemde karakterin animasyonu sayesinde böylece fazla zıplamış gözüküyor bunu nasıl düzeltebilirim

  4. Arda dedi ki:

    merhaba öncelikle ben unity ye yeni başladım ve karakter animasyonlarını yapıyordum
    if (Input.GetKey(KeyCode.W) && (Input.GetKey(KeyCode.V)))
    {
    transform.Translate(transform.forward * 0.3f);
    anim.speed = 1;
    anim.SetBool(“TAKLA”, true);
    }
    if (Input.GetKeyUp(KeyCode.V))
    {
    transform.Translate(transform.forward * 0.3f);
    anim.speed = 1;
    anim.SetBool(“TAKLA”, false);
    }
    ben 2 .if de transformdan önce bekle kullanmak istiyorum oyun hata veriyor bunu yaptığımda
    yani kısaca sorunum şu ben W + V tuşuna bastığımda takla atacak ama basılı tutmam gerekiyor
    alttaki if kısmını eklemezsem bu olayı sürekli tekrar ediyor.

    ben sizin anlattığınız kısımda IEnumerator bunu anlamadım galiba oyuzden yapamadım void update altına yazıyorum kodlarımı şimdiden teşekkürler

    • yasirkula dedi ki:

      Animasyonlar arası geçiş kötü durduğu için biraz beklemek istiyorsunuz diye düşünüyorum. Bence karakterin AnimatorController asset’ini açın (Window-Animator penceresini açıp AnimatorController’a Project panelinden çift tıklayın), ardından TAKLA false olduğunda gerçekleşen geçişe tıklayın ve Inspector’dan Settings’teki ayarları biraz düzenleyin (dokümantasyon: https://docs.unity3d.com/Manual/class-Transition.html). Örneğin Exit Time’ın değerini değiştirmeyi deneyebilirsiniz (0 ile 1 arasında değerler deneyin).

      • Arda dedi ki:

        demek istediğim şu ben tek tıklamada yapmak istiyorum ama ozaman animasyon iptal oluyor yani yaptığım komutta basılı tutmam gerekiyor

      • yasirkula dedi ki:

        Boolean değil de Trigger değişkeniniz olsun ve anim.SetTrigger(“TAKLA”) fonksiyonu ile bunu aktifleştirerek takla animasyonuna geçiş yapın. Takla animasyonundan normal animasyona geri geçişte bir Condition kullanmayın, hata alırsanız Exit Time condition’ı kullanın.

      • Arda dedi ki:

        bu sefer sonsuz döngü oldu yani sürekli takla atıyor sizide yoruyorum kusura bakmayın

      • yasirkula dedi ki:

        SetTrigger sürekli çağrılıyor demek ki. SetTrigger’ın olduğu satıra Debug.Log ekleyerek de bunu tespit edebilirsiniz. SetTrigger’ı sadece karakterin takla atmasını istediğinizde çağırın.

  5. L dedi ki:

    Yasir bey iyi akşamlar .
    Benim oyunumda iki karakter var ikisinin healt ı box collider is triger seçeneği seçili vaziyette . Ben bu iki karakterin birbirlerinin içinden geçmemesini nasıl yaparım . ( Herbirine bir collider daha verdim is triger seçili değil , bu şekilde de savruluyorlar . ) Yardım ricası ile kolay gelsin .

    • yasirkula dedi ki:

      Birbirinin içinden geçemediğini ama temas ettiklerinde bi titreştiklerini anlıyorum, yanlışım varsa düzeltin. Eğer transform.Translate ile hareket ediyorsanız Rigidbody’nin MovePosition’ını kullanmayı deneyebilirsiniz.

      • Levent dedi ki:

        Yasir bey
        Hareket için GetAxis kullanıyorum .Benim istediğim iki karakterde birbirine temas ettiğinde hareket etmemeli .Misal bir duvara yada engele karakter dokunduğu zaman onu nasıl geçemiyorsa oyuncunun başka bir tarafa yönlendirmesiyle gidiyorsa bende o şekilde yapmaya çalışıyorum .
        Teşekkurler.

      • yasirkula dedi ki:

        Eğer MovePosition işe yaramadıysa maalesef bir fikrim yok :/

  6. Levent dedi ki:

    Yasir bey
    Yaptığım bir oyunda (Samsung app ta yayınladım askıya alındı .) canvasta olan joystyic, buttonlar , karakterin yaşam çizgisi farklı boyutlardaki telefon veya tabletlerde şeklinin bozulduğu veya kaybolup görünmediği ile bilgili bildirim aldım . Her boyutta ve çözünürlükte cihaza uygun olarak nasıl yapabilirim .
    Yardım ricası ile kolay gelsin .

  7. oğuz dedi ki:

    Merhaba Yasir hocam ufak bir sorum olacaktı.

    Oyun menüsünde butona basılınca coroutine ile ekranda 1.texti gösteriyorum ve belli bir saniye sonra text objesini destroy ediyorum. Oyuncu aynı butona tekrar basınca 2.text objesini göstermek istiyorum ama burada sıkıntı oluyor.

    Nasıl yapabilirim acaba ? Coroutine’nin içine ikinci bir if bloğu ekleyerek yapmaya çalıştım ama her seferinde direkt 2.text’i ekrana yazdırdı.

    Yardımlarını bekliyorum kolay gelsin hocam.

    • yasirkula dedi ki:

      Bir “bool text1Gozuktu = false;” değişkeniniz olsun. Bunun değeri false ise ilk text’i gösterin ve değişkeni true yapın, değeri true ise de ikinci text’i gösterin.

  8. Levent dedi ki:

    Yasir bey iyi akşamlar ben yuzey objesine collider vermek istiyorum yuzey çok girintili çıkıntılı olduğu için mesh collider vereceğim convex yapıp yüzeyde olan objelerin düşmemesini sağlamak istiyorum fakat mesh girinti ve çıkıntılara uymuyor kare şeklinde çıkıyor convex i kapatınca tam yuzeye colider oturuyor bu seferde objeler üstünden düşüyor. Yardım ricası ile kolay gelsin .

    • Levent dedi ki:

      Yasir bey bir türlü yapamadım .Onun yerini tek tek collider verdim .Uzun sürdü ama oluyor .

    • yasirkula dedi ki:

      Unity’nin dokümantasyonunda yazdığına göre, yüzeyde Rigidbody component’i olmazsa Mesh Collider’daki Convex’in işaretini kaldırabilirmişsiniz ve sistem düzgün çalışırmış. Ama kendim test etmedim. Bu işe yaramazsa da ya bir plugin kullanmalı (“unity concave collider” şeklinde arama yapabilir) ya da tek tek collider vermeye devam etmelisiniz.

  9. Uğur dedi ki:

    Öncelikle bu site için teşekkürler. Ben bilgisayara karşı bir satranç oyunu yapsam, ben bir taş oynayınca bilgisayarda bir taş oynayacak, bu sistemde sıra bana gelene kadar ben bekleyeceğim, sıra bana gelince bilgisayar bekleyecek. Burada bir fonksiyonun işlemi bittikten sonra başka bir fonksiyonun bitmesini beklemesini nasıl sağlayabilirim.

    • yasirkula dedi ki:

      Bir coroutine’de while(birDegisken==true) yield return null; kodu yazarak birDegisken’in değeri false olana kadar o coroutine’i bekletebilirsiniz.

    • Erhan AYGÖREN dedi ki:

      Coroutine fonksiyonu ile halledebilirsin sanırım. Aynı sorunu ben yield return new WaitUntil( () => (değerlendirilecek ifade)) komutu ile çözmüştüm.

  10. Erhan AYGÖREN dedi ki:

    Merhaba Yasir Bey,

    Ben Unity ile basit oyunlar geliştiriyorum. Geliştirmekte olduğum bir uygulama da girilen konutları stackleyip, başlama butonu ile stackdeki komutları teker teker gerçekleştirmek istiyorum. Girilen komutları diziye atıp döngüler ile işliyorum. Komutlar, ileri gitme, sağa ve sola dönme ve geri gitmeden oluşuyor. Sorunum şu; hareket etme işlemini anında gerçekleştiriyor bense her bir adımı 1 saniye gibi bir zamanda gerçekleştirmesini istiyorum uygulamanın daha anlaşılır olması için. Hareket etme işlemini Canvas’a yerleştirdiğim 4×4 lük panellerin position bilgisi ile gerçekleştiriyorum. Sorunumu Coroutine ile çözebilir miyim? Şimdiden teşekkürler saygılarımla iyi çalışmalar.

    Uygulamanın görüntüsü; https://i.hizliresim.com/JZMEjY.jpg

    • yasirkula dedi ki:

      Evet coroutine işinizi görür. Her bir komut arasında bir yield return new WaitForSeconds(1.0f); çalıştırarak 1 saniye bekleyebilirsiniz.

  11. julinan dedi ki:

    –Konuyla alakasız–
    Merhaba ben bir shooter oyunu yapıyorum.Elimde bir spawner var bunun sayesinde bir çok düşman oluşturabiliyorum yaptığım kodlarda eğer düşmanla aramadaki mesafe 1.5 den küçükse benim canımın azalması şeklinde ayarlı ama bu işlem sadece bir düşman için geçerli çevremdeki her düşmanla aramdaki mesafeyi ölçmesini nasıl sağlarım ?

    • yasirkula dedi ki:

      Component’i player’a vermek yerine düşman prefab’ına verebilirsiniz, böylece her düşman kendi mesafesini kendi ölçer. Daha iyisi ise, tüm düşmanları bir List veya array’de tutabilir ve bu listenin içindeki tüm düşmanların player’a mesafesini tek tek ölçebilirsiniz.

      • julinan3 dedi ki:

        Component’i düşman prefab’ına vermeyide denedim çalıştı hepsi izliyor,vuruyor falan ama can barım sıkıntı oluyo bazıları scriptte canımı götürüyo gözüküyor ama bar azalmıyor bazen script sadece son oluşan klonda is görüyor.

      • yasirkula dedi ki:

        Can barı script’iniz nasıl ve ne zaman güncelleniyor bilmediğimden bu konuda pek yardımcı olamayacağım. Player’a hasar verdikçe can barını da güncellemeniz lazım normalde.

  12. Sami dedi ki:

    –Konuyla Alakası Yok–
    Ben Unity de Monodevelop Kullanıyorum Yeni Bir Kod Yazdıkdan Sonra Monodevelop da f5 e Basmadan yada Debug Yapmadan Unity Yeni Yazdığım Kodu Görmüyor Bunu Nasıl Çözebilirim

  13. Levent dedi ki:

    Yasir bey klonlama yaparken (Instantite) for döngüsü kullanarak (int i=0;i<2;i++)start ta yazınca sadece 2 adet kolonluyor azalınca artırmıyor update ye yazınca sınırsız olarak arttırıyor .klonlanan nesne ikiden az olunca tekrardan sadece iki taneyi instante edemedim . Nasıl yapabilirim . Yardım ricasıyla kolay gelsin .

    • yasirkula dedi ki:

      Kodu Start’ta bırakın ve objeye verdiğiniz script’in OnDestroy fonksiyonunda yeni bir obje Instantiate edin. Böylece bir obje yok olunca yeni bir obje oluşacak. Daha da iyisi, yeni bir obje Instantiate etmek yerine var olan objenin yerini değiştirmek suretiyle o objeyi tekrar kullanın; ama bu işlemi OnDestroy’da değil, objeyi nerede Destroy ediyorsanız orada yapmanız lazım.

  14. Emirhan Koçoğlu dedi ki:

    Size bişey sormak istiyorum. Coroutinelerle alakası yok farkındayım.Ben bir bool tanımladım ve eğer bu bool açıksa bir gameobject tanımlamasını istiyorum yani şöyle

    public bool asd
    if(asd){
    public GameObject dsa
    }

    Ama bu kodu
    ****——-if(asd){
    public GameObject dsa
    }———-****
    Setup Veya Updatenşn içine yazdığımda sıkıntı veriyor çözümü varmı
    Bu arada bir strateji oyunu yapmak istiyorum
    Şimdiden teşekkürler.

  15. Levent dedi ki:

    Destroy ettiğim enemy objesi silinince ses kayboluyor .destroyu bu sistemde geciktiremedim . Nasıl yapmalıyım : patSesi.PlayOneShot (PatlamaSesi, 0.1f);

  16. Batuhan Mafratoglu dedi ki:

    Abi ben playerprefs A sahnesinde altin degerini alip B sahnesindeki magza yerini yazdirmak istiyorum bunu nasil yapabilirim bi turlu yapamadim

    • Batuhan Mafratoğlu dedi ki:

      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      using UnityEngine.SceneManagement;
      using UnityEngine.UI;
      using System;

      public class Menu : MonoBehaviour {

      public GameObject menucanvas;
      public GameObject settingcanvas;
      public GameObject shopcanvas;
      public GameObject infocanvas;
      public GameObject backbtn;
      public Toggle mutetog;
      public Toggle shoptog;
      public Text infotext;
      int newaltin;
      public static int totalaltin;
      public Text toplamaltintext;
      public Text bincoinstext;

      void Start ()
      {
      newaltin = PlayerPrefs.GetInt(“Altin”);
      totalaltin = Rabbit.altindeger;
      newaltin = Convert.ToInt32(toplamaltintext);

      }

      void Update ()
      {
      totalaltin += newaltin;
      PlayerPrefs.SetInt(“Altin”, totalaltin);
      toplamaltintext.text = totalaltin.ToString();

      }

      public void Playbutton()
      {
      menucanvas.SetActive(false);
      settingcanvas.SetActive(false);
      SceneManager.LoadScene(1);
      }

      public void Settingsbutton()
      {
      menucanvas.SetActive(false);
      settingcanvas.SetActive(true);
      }

      public void Shopbutton()
      {
      menucanvas.SetActive(false);
      shopcanvas.SetActive(true);

      }

      public void Backbutton()
      {
      if (mutetog.isActiveAndEnabled==true)
      {
      menucanvas.SetActive(true);
      settingcanvas.SetActive(false);
      }
      else if (shoptog.isActiveAndEnabled == true)
      {
      menucanvas.SetActive(true);
      shopcanvas.SetActive(false);
      }
      else if (infotext.isActiveAndEnabled == true)
      {
      infotext.gameObject.SetActive(false);
      settingcanvas.SetActive(true);
      backbtn.SetActive(false);
      }

      }

      public void Infobutton()
      {
      settingcanvas.SetActive(false);
      infocanvas.SetActive(true);
      infotext.gameObject.SetActive(true);
      backbtn.SetActive(true);
      }

      public void Exitbutton()
      {
      Application.Quit();
      }

      public void Bincoins()
      {
      if(Rabbit.altinvalue == 2000)
      {
      Debug.Log(“Satın alındı”);
      Rabbit.altinvalue -= 2000;
      }
      else
      {
      Debug.Log(“Para Yeterli Değil”);
      }

      }

      private void OnApplicationQuit()
      {
      PlayerPrefs.SetInt(“Altin”, totalaltin);
      }
      }

      • yasirkula dedi ki:

        A sahnesinde altının değerini kaydetmek için PlayerPrefs.SetInt(“Altin”, altın miktarı) fonksiyonunu kullanıp B sahnesinde bu değere PlayerPrefs.GetInt(“Altin”) şeklinde erişebilirsiniz. Attığınız kod static değişkenlerle vs. karmaşık geldi ben onu tam çözemedim.

  17. Dilaver dedi ki:

    Harika bir ders herkesin işine yaricaktir teşekkürler hocam

yasirkula için bir cevap yazın Cevabı iptal et

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 )

Google fotoğrafı

Google 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.