Coroutine normal fonksiyon gibi düşünülebilir fakat tek bir farkı vardır, o da kod bloğunu bekletme özelliğidir.
Coroutine’ler IEnumerator döndürmek zorundadır bu yüzden Using System.Collections; kullanılır.
Ne kadar doğru olur bilmiyorum ama Coroutine‘leri Invoke fonksiyonu gibi düşünebilirsiniz. Invoke kullanarak bir fonksiyonu delaylı şekilde çalıştırabiliyorduk. Örneklere geçmeden Coroutine’leri nerelerde kullandığımı söylemek istiyorum. Level sonunda Canvas’ta SUCCESS paneli çıkartmamız gerekiyordu, ama bunu level bittikten birkaç saniye sonra yapmalıydık. Bu durumda aklıma ilk olarak Coroutine geldi ve uyguladım. Ek olarak herhangi bir gecikmeli işlem yaptırmak istiyorsak Coroutine işimizi görecektir.
Coroutine’ler ayrı bir thread(iş parçacığı)’de çalışmaz. Unity’nin ana thread’inde yürütülür.
Kullanım Örnekleri:
- HTTP aktarımlarını beklemek
- Dosyaların yüklenmesini beklemek
- Her frame’de kontrol ettirilmesi yük bindirecek şeylerde …
Geçelim örneklere;
private IEnumerator CoroutineTest()
{
Debug.Log("Coroutine çalışmaya başladı");
yield return new WaitForSeconds(1f);
Debug.Log("Coroutine çalışmaya başladıktan sonra 1 saniye geçti");
}
Coroutine fonksiyonu tanımladım ve fonksiyon çalışınca ilk olarak “Coroutine çalışmaya başladı” debug’unu elde ettik, sonra yield return new WaitForSeconds(1f); diyerek kod bloğunu 1 saniye beklettim ve ardından “Coroutine çalışmaya başladıktan sonra 1 saniye geçti” debug’unu elde ettim. Mantık bu şekilde. İstersem fonksiyona girer girmez yield return yazarak bekletebilirim ister sonunda, hangisi işinize gelirse.
IEnumerator CoroutineTest()
{
Debug.Log("Zaman: " + Time.time);
yield return new WaitForSeconds(1.5f); // 1.5 saniye bekle
Debug.Log("Zaman: " + Time.time);
}
İkinci örnekte o anki zamanı debug attırarak daha iyi anlayabilirsiniz bahsettiğim mantığı.
Burdaki zaman time.timeScale’e bağlıdır. TimeScale’niz kod çalışırken farklı olursa kod onu referans alarak çalışacaktır. Default olarak timeScale 1 gelir fakat ihtiyaca göre değiştirebilirsiniz. Eğer timeScale’den etkilenmesini istemiyorsanız WaitForSecondsRealtime kullanabilirsiniz.
Coroutine’leri Durdurma Ve Başlatma
Oluşturduğumuz Coroutine’leri başlatma ve durdurma ihtiyacı duyarız. Bu durumda belli başlı fonksiyonlar ihtiyacımızı karşılayacak.
StartCoroutine() Coroutine’mizi başlatır.
StopCoroutine() Coroutine’mizi sonlandırır.
StopAllCoroutine() o class’daki tüm Coroutine’lerimizi sonlandırır.
Ek olarak bir konudan daha bahsetmek istiyorum. Unity’de Garbage Collector(GC) thread, static ve numerator gibi durumları siz komut vermezseniz temizlenmiyor. Coroutine’ler doğası gereği çok çöp ürettiğinden eğer işiniz bittikten sonra StopAllCoroutine diyerek veya değişkene atadığımız coroutine’yi durdurduğumuzda üretilen çöpler temizlenecektir aksi halde GC üzerine sorumluluk alıp temizleme işlemi yapmıyor 🙂
void Start()
{
StartCoroutine(CoroutineTest());
StopCoroutine(CoroutineTest());
StopAllCoroutines();
}
Bekletme Seçenekleri
yield return new WaitForSeconds(1.5f); // 1.5 saniye bekle
yield return new WaitForEndOfFrame(); //Thread'in bulunduğu frame'in bitmesini bekler
yield return new WaitForFixedUpdate(); //Bir sonraki FixedUpdate frame'ini bekler
yield return new WaitForSecondsRealtime(1f); //TimeScale'e bağlı olmadan 1 saniye bekler