راهنمای کامل Coroutine در یونیتی: از سطح مبتدی تا پیشرفته
در توسعه بازی با موتور Unity، یکی از پرکاربردترین ابزارها برای اجرای عملیات غیرهمزمان، استفاده از Coroutine است. این قابلیت به شما امکان میدهد اجرای تابعی را متوقف کرده و بعد از مدتی ادامه دهید، بدون آنکه بازی هنگ کند یا نیاز به مدیریت پیچیده Threadها داشته باشید.
✔️ Coroutine چیست؟
Coroutine یک روش اجرای تابع بهصورت غیرهمزمان و تدریجی است. یعنی میتوانید اجرای یک تابع را متوقف کنید، کمی صبر کنید و سپس ادامه دهید. این کار با استفاده از کلیدواژه yield
انجام میشود.
📌 نحوه شروع یک Coroutine
void Start() { StartCoroutine(MyRoutine()); } IEnumerator MyRoutine() { Debug.Log("شروع"); yield return new WaitForSeconds(2f); // توقف به مدت ۲ ثانیه Debug.Log("ادامه بعد از ۲ ثانیه"); }
📘 انواع دستورهای yield و کاربردشان
yield return null
– صبر تا فریم بعدیyield return new WaitForSeconds(float t)
– صبر به مدت مشخصyield return new WaitUntil(() => condition)
– صبر تا برقرار شدن شرطyield return new WaitWhile(() => condition)
– صبر تا رفع شدن شرطyield return new WaitForEndOfFrame()
– ادامه بعد از اتمام فریم فعلیyield return new WaitForFixedUpdate()
– ادامه در FixedUpdate بعدیyield return StartCoroutine(AnotherCoroutine())
– اجرای Coroutine تو در تو
📂 ذخیره و توقف Coroutine
Coroutine routine; void Start() { routine = StartCoroutine(MyRoutine()); } void Stop() { StopCoroutine(routine); }
🎯 کنترل دقیق با نام Coroutine
StartCoroutine("MyRoutine"); // اجرای تابع با نام StopCoroutine("MyRoutine"); // توقف با نام
✅ نکات حرفهای و موارد استفاده
- 🌀 انیمیشن تدریجی بدون استفاده از Update
- 📥 دانلود و بارگذاری فایلها (در کنار UnityWebRequest)
- 🗣️ سیستم دیالوگ با تایمبندی مرحلهای
- 🧠 هوش مصنوعی با تأخیر در تصمیمگیری
- 🔁 سیستم حمله و دفاع دورهای (cooldown)
Coroutineها در Unity امکانات زیادی دارن که میتونن عملکرد بازی رو روانتر و ساختارمندتر کنن. در اینجا برخی از مهمترین کاربردهای حرفهای اونها رو همراه با مثال بررسی میکنیم:
- 🌀 انیمیشن تدریجی بدون استفاده از Update:برای جابهجایی یا تغییر رنگ یک آبجکت بهمرور زمان:
IEnumerator MoveOverTime(Transform obj, Vector3 target, float duration) { Vector3 start = obj.position; float elapsed = 0f; while (elapsed < duration) { obj.position = Vector3.Lerp(start, target, elapsed / duration); elapsed += Time.deltaTime; yield return null; } obj.position = target; }
- 📥 دانلود و بارگذاری فایلها (در کنار UnityWebRequest):مناسب برای دریافت داده از اینترنت یا سرور:
IEnumerator DownloadData() { UnityWebRequest www = UnityWebRequest.Get("https://example.com/data"); yield return www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) Debug.Log("دریافت شد: " + www.downloadHandler.text); else Debug.LogError("خطا: " + www.error); }
- 🗣️ سیستم دیالوگ مرحلهای (با تأخیر بین هر خط):برای نمایش دیالوگ با فاصله زمانی بین جملات:
public Text dialogText; string[] lines = { "سلام!", "به بازی خوش آمدی.", "آمادهای؟" }; IEnumerator ShowDialog(string[] lines) { foreach (string line in lines) { dialogText.text = line; yield return new WaitForSeconds(2f); } dialogText.text = ""; }
- 🧠 هوش مصنوعی با تأخیر در تصمیمگیری:برای اجرای حرکات دشمن به صورت نوبتی:
IEnumerator EnemyRoutine() { while (true) { DecideNextMove(); yield return new WaitForSeconds(1.5f); // تأخیر بین حرکات } } void DecideNextMove() { // الگوریتم تصمیمگیری دشمن Debug.Log("AI حرکت کرد"); }
- 🔁 سیستم حمله و دفاع دورهای (Cooldown):برای حملات که باید مدتی صبر کرد تا دوباره فعال شوند:
bool canAttack = true; void TryAttack() { if (canAttack) { StartCoroutine(AttackCooldown()); } } IEnumerator AttackCooldown() { canAttack = false; Debug.Log("حمله انجام شد"); yield return new WaitForSeconds(3f); canAttack = true; }
- 🟩 شبیهسازی نوار آپدیت فیک (Fake Update Bar):یک نوار پیشرفت ساختگی برای نمایش پیشرفت ظاهری:
public Slider progressBar; void Start() { StartCoroutine(FakeUpdateRoutine()); } IEnumerator FakeUpdateRoutine() { float progress = 0f; while (progress < 1f) { progress += 0.01f; progressBar.value = progress; yield return new WaitForSeconds(0.05f); } Debug.Log("آپدیت فیک تمام شد!"); }
🛠️ شبیهسازی آپدیت فیک با Coroutine
یکی از کاربردهای جالب Coroutine، شبیهسازی یک نوار پیشرفت ظاهری (fake loading bar) است. این تکنیک برای نشان دادن بارگذاری بین مراحل، نصب یا همگامسازی اطلاعات خیلی مفیده.
using UnityEngine; using UnityEngine.UI; using System.Collections; public class FakeLoader : MonoBehaviour { public Slider progressBar; void Start() { StartCoroutine(FakeUpdateRoutine()); } IEnumerator FakeUpdateRoutine() { float progress = 0f; while (progress < 1f) { progress += 0.01f; progressBar.value = progress; yield return new WaitForSeconds(0.05f); } Debug.Log("آپدیت فیک تمام شد!"); } }
میتونی زمان، سرعت یا نوع افزایش رو به دلخواه تغییر بدی تا حس طبیعیتری به کاربر منتقل بشه.
🚫 اشتباهات رایج
- عدم متوقف کردن Coroutine پس از ناپدید شدن گیمآبجکت
- استفاده از Coroutine برای محاسبات سنگین (بهتره از Thread یا Task استفاده شه)
- نادیده گرفتن memory leak در طولانی مدت
👨💻 پیشرفتهتر: اجرای همزمان چند Coroutine
void Start() { StartCoroutine(RunAll()); } IEnumerator RunAll() { yield return StartCoroutine(FirstTask()); yield return StartCoroutine(SecondTask()); } IEnumerator FirstTask() { Debug.Log("اولی شروع شد"); yield return new WaitForSeconds(1f); Debug.Log("اولی تمام شد"); } IEnumerator SecondTask() { Debug.Log("دومی شروع شد"); yield return new WaitForSeconds(2f); Debug.Log("دومی تمام شد"); }
📊 مزایا
- سادگی در کنترل زمان و فریم
- کاهش نیاز به مدیریت دستی زمان
- افزایش خوانایی کد
- کنترل دقیق روی توالی عملیاتها
⚠️ معایب
- نیاز به اجرای داخل MonoBehaviour
- عدم پشتیبانی از بازگشت مقدار (return value)
- محدودیت در مدیریت خطا (try/catch محدود)
🎓 نتیجهگیری
Coroutine ابزاری بسیار مفید برای توسعهدهندگان Unity است که اجرای تابعها را به شکل کنترلشده و زمانبندیشده ممکن میکند. با درک عمیقتر آن و استفاده از ترکیبهای مختلف yield
، میتوانید سیستمهایی بسیار انعطافپذیر، بهینه و روان بسازید.