ฉันควรใช้ Async & Await แทน Coroutines ใน Unity หรือไม่

Aug 18 2020

ฉันควรใช้ Async & Await ใน Unity หรือไม่ หรือฉันควรใช้ Coroutines ต่อไป? หากฉันควรใช้ Async & Await ฉันจะทำเช่นนั้นให้เทียบเคียงกับ Coroutines ได้อย่างไร

คำตอบ

2 Kevin Aug 19 2020 at 01:04

ตรงกันข้ามกับคำตอบของ Evorlor นี่คือเหตุผลที่ดีในการใช้ Coroutines:

  • พวกเขาเป็นโซลูชันมาตรฐานใน Unity มาหลายปีแล้วและใครก็ตามที่คุณนำเข้ามาในทีมก็น่าจะพอใจกับพวกเขาแล้ว
  • พวกเขาอยู่ในขั้นตอนเดียวกับเครื่องยนต์ WaitForFixedUpdate()ตรวจสอบให้แน่ใจว่าขั้นตอนต่อไปใน Coroutine จะทำงานในระหว่างรอบการอัปเดตแบบคงที่ WaitForEndOfFrame()ตรวจสอบให้แน่ใจว่าขั้นตอนต่อไปจะถูกรันในรอบการอัปเดต หากคุณใช้ async / await ของ C # ไม่มีวิธีใดที่จะตรวจสอบให้แน่ใจว่ามีความซับซ้อนเพื่อให้แน่ใจว่าโค้ดยังคงอยู่ในขั้นตอนของเครื่องยนต์ (ดูความคิดเห็น)
  • ในทำนองเดียวกันWaitForSeconds()จะใช้เวลาในปัจจุบันเข้าสู่การพิจารณาสิ่งที่เป็นไปไม่ได้ด้วยTime.timeScaleawait
  • โครูทีนจะหยุดทำงานโดยอัตโนมัติเมื่ออ็อบเจ็กต์ที่รันอยู่นั้นถูกทำลายหรือปิดใช้งาน (บางครั้งอาจไม่เป็นที่ต้องการซึ่งในกรณีนี้คุณอาจต้องการ async / await)

หมายเหตุอีกประการหนึ่ง: Evorlor แนะนำวิธีแก้ปัญหานี้เพื่อรอเงื่อนไข:

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

นั่นเป็นเรื่องธรรมดา แต่ไม่ใช่วิธีแก้ปัญหาสำหรับการรอเงื่อนไข โซลูชันที่ต้องการมีแผ่นสำเร็จรูปน้อยกว่า (และอาจมีค่าใช้จ่าย CPU น้อยกว่า):

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

เมื่อใดที่ฉันไม่ควรใช้โครูทีน

  • เมื่อคุณต้องการให้ฟังก์ชันที่เหมือนโครูทีนส่งคืนค่า (ดูบล็อกโพสต์นี้แนะนำโดย DMGregory)
  • หากคุณประสบปัญหาในการจัดการข้อผิดพลาดในการทำงานกับโครูทีนของคุณ (ดูบล็อกโพสต์จากสัญลักษณ์แสดงหัวข้อย่อยก่อนหน้านี้โปรดทราบว่าคุณสามารถใส่บล็อกลองจับในโครูทีนได้ตราบใดที่บล็อกนั้นไม่มีคำสั่ง "ผลตอบแทน") .
  • หากคุณทำโปรไฟล์แอปพลิเคชันของคุณและพบว่าโครูทีนทำให้คุณเสียค่าใช้จ่ายด้านประสิทธิภาพที่คุณไม่สามารถสำรองไว้ได้และไม่สามารถแก้ไขได้โดยการเพิ่มประสิทธิภาพโครูทีนของคุณ (ไม่น่าจะเป็นไปได้สำหรับเกมส่วนใหญ่)
  • หากคุณต้องการเรียกใช้ฟังก์ชันคล้ายโครูทีนจากคลาส C # ปกติที่ไม่ขยาย MonoBehaviour
  • หากคุณต้องการฟังก์ชั่นที่เหมือนโครูทีนเพื่อให้ทำงานต่อไปเมื่อ GameObject ถูกทำลายหรือปิดใช้งาน
  • เมื่อทำงานกับไลบรารีที่ใช้งานหนักasync(เช่น Google Firebase)
  • เมื่อรหัสของคุณต้องขนานกัน (มัลติเธรด) แม้ว่าพวกเขาจะสามารถใช้ในการปรับปรุงประสิทธิภาพการทำงานโดยการกระจายการดำเนินการที่มีราคาแพงกว่าเฟรมหลายCoroutines ไม่ได้ threaded เมื่อคุณต้องการโค้ดแบบมัลติเธรดเพื่อประสิทธิภาพสูงสุดให้ใช้ C # เธรดหรือ Unity Job System
  • หากคุณมีเหตุผลที่ดีอื่น ๆที่จะไม่ใช้โครูทีน

จากประสบการณ์ของฉันข้อยกเว้นทั้งหมดนี้หายากมากและโดยปกติคุณไม่จำเป็นต้องพิจารณา YMMV ขึ้นอยู่กับโครงการและรูปแบบการเข้ารหัสของคุณ