Unity'de Coroutines yerine Async & Await kullanmalı mıyım?

Aug 18 2020

Unity'de Async & Await kullanmalı mıyım? Yoksa Coroutines'i kullanmaya devam etmeli miyim? Async & Await kullanmam gerekirse, bunu Coroutines ile karşılaştırılabilir bir şekilde nasıl yapabilirim?

Yanıtlar

2 Kevin Aug 19 2020 at 01:04

Evorlor'un cevabının aksine, işte Coroutines'i kullanmak için bazı iyi nedenler:

  • Yıllardır Unity'de standart çözüm oldular ve takıma getirdiğiniz diğer herkes onlarla zaten rahat olmalı.
  • Motora ayak uyduruyorlar. WaitForFixedUpdate()Coroutine'deki bir sonraki adımın Sabit Güncelleme döngüsü sırasında çalıştırılmasını sağlar. WaitForEndOfFrame()bir sonraki adımın Güncelleme döngüsünde çalıştırılmasını sağlar. C # 'ın eşzamansız / beklemesini kullanırsanız, kodun motorla aynı adımda kalmasını sağlamanın karmaşık olduğundan emin olmanın bir yolu yoktur (yorumlara bakın).
  • Aynı şekilde, mümkün olmayan bir şeyi de dikkate WaitForSeconds()alır .Time.timeScaleawait
  • Coroutinler, onları çalıştıran nesne yok edildiğinde veya devre dışı bırakıldığında otomatik olarak durdurulur (bu bazen istenmeyen bir durumdur, bu durumda async / await isteyebilirsiniz).

Başka bir not: Evorlor, bir durumu beklemek için bu çözümü önerdi:

//Wait until condition has been met
while (!ConditionMet())
{
    yield return new WaitForEndOfFrame();
    Debug.Log("Condition has been met.");
}

Bu yaygındır, ancak bir durumu beklemek için amaçlanan çözüm değildir. Amaçlanan çözüm daha az standart şablona (ve muhtemelen daha az CPU ek yüküne) sahiptir:

yield return new WaitUntil(() => ConditionMet());

Ne zaman gerekir değil coroutines kullanılır?

  • Coroutine benzeri bir işlevin bir değer döndürmesini istediğinizde ( DMGregory tarafından önerilen bu blog gönderisine bakın)
  • Eğer eşyordamın çalışmak için hata işlemeyi alma sorun yaşıyorsanız (önceki kurşunuyla blog yazısı bkz. Not bunu yapabilirsiniz blok, bir "verim" talimatı içermez sürece, bir eşyordamın bir try-catch bloğu koymak) .
  • Uygulamanızın profilini çıkardıysanız ve eşgüdümlerin yedekleyemeyeceğiniz performans ek yüküne mal olduğunu fark ettiyseniz ve bu, eşgüdümlerinizi optimize ederek düzeltilemez (çoğu oyun için olası değildir)
  • Normal bir C # sınıfından coroutine benzeri bir işlevi çalıştırmanız gerekirse MonoBehaviour
  • GameObject'i yok edildiğinde veya devre dışı bırakıldığında çalışmaya devam etmek için coroutine benzeri bir işleve ihtiyacınız varsa.
  • Yoğun kullanımda olan bir kitaplıkla çalışırken async(ör. Google Firebase)
  • Kodunuzun paralel olması gerektiğinde (çok iş parçacıklı). Pahalı bir işlemi birden çok çerçeveye dağıtarak performansı artırmak için kullanılabildikleri halde, Coroutine'ler iş parçacığına sahip değildir . Maksimum performans için çok iş parçacıklı koda ihtiyacınız olduğunda, C # Threads veya Unity Job System kullanın.
  • Koroutinleri kullanmamak için başka iyi bir nedeniniz varsa

Tecrübelerime göre, bu istisnaların tümü çok nadirdir ve normalde bunları dikkate almanıza gerek yoktur. YMMV, projeye ve kodlama stilinize bağlı olarak.