دستورات اجرای کد
متدهای Invoke
متدهای Invoke متدهایی هستند که میتوانند متد دیگری را در زمان دلخواه توسعهدهنده فراخوانی کنند.
Invoke
متد متد Invoke
میتواند پس از طی یک بازهی زمانی متد دیگری را فراخوانی کند. برای استفاده از Invoke ابتدا متد جدیدی (در همان اسکریپت) تعریف کرده و کدهای موردنظر را درون آن مینویسیم. سپس از دستور زیر استفاده میکنیم:
پارامتر اول: نام متد / پارامتر دوم: مدت زمان تاخیر از زمان اجرای Invoke
نکته
اگر از Invoke در متدهایی که چندین بار تکرار میشوند (مثل Update
) استفاده شود، دستورات درون متد MyMethod
پس از طی شدن زمان Invoke مطابق با تعداد دفعات اجرای متدی که درون آن قرار دارند (مثل Update
) اجرا خواهند شد.
InvokeRepeating
متد متد InvokeRepeating
میتواند متد دیگری را در بازههای زمانی منظم فراخوانی کند. برای مثال در صورتی که قصد داشته باشیم یک تفنگ هر 5 ثانیه یک بار شلیک کند کد شلیک را درون متدی به نام Shoot
(در همان اسکریپت) نوشته و آن را توسط InvokeRepeating فراخوانی میکنیم:
پارامتر اول: نام متد / پارامتر دوم: مدت زمان اولین تاخیر / پارامتر سوم: بازههای زمانی وقفههای بعدی
نکته
متد InvokeRepeating
در توابعی که تنها یک بار اجرا میشوند به درستی عمل میکند. یعنی برای مثال اگر این متد در Update
اجرا شود پس از گذشت مدت زمان اولین تاخیر متد Shoot
متناوباً شروع به اجرا خواهد کرد و عملکرد صحیحی نخواهد داشت.
استفاده از متدهای Invoke دارای معایب زیادی است. از جمله عدم امکان متوقف کردن آنها به صورت جداگانه و به تفکیک نام (برای متوقف کردن تمام Invokeهای در حال اجرا از قطعه کد CancelInvoke()
استفاده میکنیم) و همچنین خطاهایی که در نکتهها بررسی کردیم. به همین منظور در توسعهی بازی معمولاً از متدهای Invoke استفاده نکرده و به ساختارهایی مانند Coroutineها روی میآوریم.
Coroutineها
در صورتی که در اسکریپتهای MonoBehaviour قصد داشته باشیم کدی را در خارج از چرخهی عمر گیم آبجکت اجرا کنیم از Coroutine استفاده میکنیم. Coroutine نوعی متد است که این امکان را فراهم میکند تا چندین کد به صورت همزمان اجرا شوند (مالتی تسکینگ).
برای مثال فرض کنید در یک صحنه از بازی قصد داریم با وارد شدن پلیر به درون collider قلمروی دشمن، گیم آبجکت دشمن شروع به حرکت کرده و به پلیر نزدیک شود. برای پیادهسازی این قابلیت باید کامپوننت Transform گیم آبجکت دشمن را دریافت کرده و با دسترسی مستقیم به پراپرتی localPosition اقدام به جابجایی آن به سمت پلیر کنیم. بدیهی است که این عمل چند ثانیه به طول میانجامد و اجرایی شدن آن نیازمند اجرای کد مربوطه در چند صد فریم میباشد. در حالی که متد OnTriggerEnter2D مربوط به قلمرو تنها یک بار اجرا میشود. برای حل این مشکل کد مربوط به حرکت دشمن را در یک Coroutine تعریف کرده و در متد نفوذ آن را صدا میزنیم. در این حالت محتویات درون Coroutine مستقل از کدهای MonoBehaviour و در یک نخ مجزا شروع به اجرا میکنند.
همچنین در صورتی که بخواهیم یک کد پس از مدت زمان معینی اجرا شود از Coroutine استفاده میکنیم.
ساختار یک Coroutine
ساختار یک Coroutine به صورت زیر است:
خروجی متدهای Coroutine از نوع IEnumerator
بوده و با استفاده از کلمهی کلیدی yield
که درون بلوک نوشته میشود میتوان اجرای دستورات را در آن نقطه تعلیق کرد.
دستورات تعلیق
دستورات تعلیق دستوراتی هستند که با ایجاد وقفههای مناسب کارکرد دلخواه را در بازی پیادهسازی کرده و یا باعث جلوگیری از کرش کردن بازی میشوند. دستورات تعلیق مهم عبارتند از:
تعلیق اجرای دستورات نخ در این نقطه تا پایان فریم
تعلیق اجرای دستورات نخ در این نقطه به مدت 2 ثانیه
کاربرد دستورات تعلیق
تعلیق تا پایان فریم (
yield return null
):در بسیاری از موارد، قصد داریم که دستورات درون Coroutine بیش از یک بار اجرا شوند (مثل متد
Update
). به این منظور از یک حلقهی تکرار همیشه صحیح مثلwhile(true)
استفاده میکنیم. اما از آنجایی که در حالت عادی یک حلقهی تکرار همیشه صحیح موجب کرش کردن برنامه میشود با نوشتنyield return null
درون حلقه به بازی این امکان را میدهیم تا پس از اجرای بلوک حلقه به فریم بعدی رفته و سپس بلوک حلقه دوباره اجرا شود.IEnumerator myCoroutine(){while (true){Debug.Log("Hello");yield return null;}}تعلیق به مدت زمان معین (
yield return new WaitForSeconds
):برای این که یک کد در بازی پس از مدت زمانی معین اجرا شود میتوان از Coroutine و دستور
yield return new WaitForSeconds
استفاده نمود. به عنوان مثال صدا زدن این Coroutine باعث میشود که پس از5
ثانیه پیامHello
در پنجرهی کنسول ادیتور نمایش داده شود:IEnumerator myCoroutine(){yield return new WaitForSeconds(5.0f);Debug.Log("Hello");}
دستورات مدیریت Coroutineها
در نهایت با استفاده از این دستورات میتوان نسبت به فراخوانی و متوقف کردن Coroutineها اقدام نمود:
شروع اجرای MyCoroutine
متوقف کردن MyCoroutine
متوقف کردن تمام Coroutineهای در حال اجرا
تمرین
تمرین: کارکرد این Coroutine را توضیح دهید و در صورت لزوم آن را اجرا کنید.