Разбираем корутины в Unity (мидл)

Разбираем корутины в Unity (мидл)

IEnumerators и корутины позволяют начинать выполнение каких-либо действий, продолжать их в течение определенного времени, а затем останавливать. Я использую их постоянно:

  • для всплесков визуальных эффектов,
  • для интерполяции движения,
  • для ожидания загрузки сцены перед получением её объектов.

Описание

Метод StartCoroutine запускает корутину.

Выполнение корутины можно приостановить в любой момент с помощью оператора yield. Когда используется yield, выполнение корутины приостанавливается и автоматически продолжается в следующем кадре. Более подробно см. документацию по корутинам.

Корутины отлично подходят для моделирования поведения, растянутого на несколько кадров. Метод StartCoroutine возвращает управление после первого yield return, однако можно выполнить yield от результата, чтобы дождаться завершения корутины.

⚠ Важно: Нет гарантии, что корутины завершатся в том же порядке, в котором были запущены, даже если они заканчиваются в одном кадре.

Любой yield (включая null) приводит к возобновлению выполнения в одном из следующих кадров, если только корутина не была остановлена или завершена.

Остановка корутин

  • Корутины можно остановить с помощью MonoBehaviour.StopCoroutine и MonoBehaviour.StopAllCoroutines.
  • Они также прекращаются при уничтожении MonoBehaviour или отключении GameObject, к которому он привязан.
  • Однако! Корутину НЕ остановит просто отключение MonoBehaviour.

Пример использования StartCoroutine:

using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { // In this example we show how to invoke a coroutine and // continue executing the function in parallel. private IEnumerator coroutine; void Start() { // - After 0 seconds, prints "Starting 0.0" // - After 0 seconds, prints "Before WaitAndPrint Finishes 0.0" // - After 2 seconds, prints "WaitAndPrint 2.0" print("Starting " + Time.time); // Start function WaitAndPrint as a coroutine. coroutine = WaitAndPrint(2.0f); StartCoroutine(coroutine); print("Before WaitAndPrint Finishes " + Time.time); } // every 2 seconds perform the print() private IEnumerator WaitAndPrint(float waitTime) { while (true) { yield return new WaitForSeconds(waitTime); print("WaitAndPrint " + Time.time); } } }

Еще пример

// In this example we show how to invoke a coroutine and wait until it // is completed using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { IEnumerator Start() { // - After 0 seconds, prints "Starting 0.0" // - After 2 seconds, prints "WaitAndPrint 2.0" // - After 2 seconds, prints "Done 2.0" print("Starting " + Time.time); // Start function WaitAndPrint as a coroutine. And wait until it is completed. // the same as yield return WaitAndPrint(2.0f); yield return StartCoroutine(WaitAndPrint(2.0f)); print("Done " + Time.time); } // suspend execution for waitTime seconds IEnumerator WaitAndPrint(float waitTime) { yield return new WaitForSeconds(waitTime); print("WaitAndPrint " + Time.time); } }

Объявление

public Coroutine StartCoroutine(string methodName, object value = null);

Описание

Запускает корутину с указанным именем метода (methodName).

В большинстве случаев предпочтительнее использовать другую версию StartCoroutine (где передается IEnumerator). Однако вызов StartCoroutine с именем метода в виде строки позволяет останавливать конкретную корутину с помощью StopCoroutine, передав то же имя метода.

⚠ Недостатки этого способа:

  • Использование строкового имени увеличивает нагрузку на производительность при запуске корутины.
  • Можно передать только один параметр.
// In this example we show how to invoke a coroutine using a string name and stop it. using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { IEnumerator Start() { StartCoroutine("DoSomething", 2.0f); yield return new WaitForSeconds(1); StopCoroutine("DoSomething"); } IEnumerator DoSomething(float someParameter) { while (true) { print("DoSomething Loop"); // Yield execution of this coroutine and return to the main loop until next frame yield return null; } } }

Созданная корутина может запустить другую корутину. Эти две корутины могут взаимодействовать различными способами:

  • Обе корутины могут выполняться параллельно.
  • Одна корутина может остановить другую, продолжая выполняться сама.

В приведённом ниже примере одна корутина приостанавливает выполнение, запуская другую. Когда вторая корутина завершается, первая перезапускается.

using System.Collections; using System.Collections.Generic; using UnityEngine; public class ExampleClass : MonoBehaviour { void Start() { StartCoroutine(coroutineA()); } IEnumerator coroutineA() { // wait for 1 second Debug.Log("coroutineA created"); yield return new WaitForSeconds(1.0f); yield return StartCoroutine(coroutineB()); Debug.Log("coroutineA running again"); } IEnumerator coroutineB() { Debug.Log("coroutineB created"); yield return new WaitForSeconds(2.5f); Debug.Log("coroutineB enables coroutineA to run"); } }

Еще больше полезного материала по геймдеву в нашем канале:

8
2
4
1
21 комментарий