Unity 6.3
0 онлайн 57 гостей 3 в системе
Вход
Программирование в Unity Шаг 34 из 210

Запись и выполнение сопроцессов

Сопутствующая программа — это метод, который может приостановить выполнение и возобновить его позже. В Unity приложениях это означает, что сопутствующие программы могут начать выполнение в одном кадре и возобновить его в другом, что позволяет распределить задачи между несколькими кадрами.

Обычные методы, не являющиеся некоррутинными, выполняются до завершения, прежде чем возвращают управление вызывающему, что во время выполнения Unity означает, что их действие завершается в пределах обновления одного кадра. В ситуациях, когда вы хотите, чтобы работа метода воздействовала на несколько кадров, например, постепенный эффект fade-out, вы можете использовать некоррутинную операцию. Некоррутинные методы также полезны для обработки длительных асинхронных операций, таких как ожидание завершения передачи HTTP, загрузки ассетов или ввода/вывода файла.

Важно: Не путать сопутствующие программы с потоками. Синхронные операции, выполняемые в сопутствующей программе, все еще выполняются на главном потоке. Если вы хотите сократить количество времени CPU, затрачиваемого на главный поток, так же важно избегать блокирования операций в сопутствующих программах, как и в любом другом скриптовом коде. Если вы хотите использовать многопоточность в Unity, у вас есть следующие варианты:

Писать сопутствующие программы

Рассмотрим задачу постепенного уменьшения альфа-значения (непрозрачности) объекта до тех пор, пока он не станет невидимым. Для того, чтобы эффект исчезновения был видимым, непрозрачность должна уменьшаться в течение последовательности кадров. Если вы пытались написать метод Fade, вы могли бы написать что-то вроде следующего:

void Fade()
{
    Color c = renderer.material.color;
    for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
    {
        c.a = alpha;
        renderer.material.color = c;
    }
}

Этот метод не является сопутствующей процедурой, так что он выполняет каждую итерацию цикла for в рамках обновления одного кадра, и объект исчезает мгновенно, вместо того, чтобы казаться выпадающим. Одним из возможных решений является добавление кода к функции Update, которая выполняет выпадение по кадрам. Однако, может быть удобнее использовать сопутствующую процедуру.

Короутины — это методы с типом возврата IEnumerator и инструкцией доходность return, включенной где-то в тело. Инструкция yield return — это точка, в которой исполнение приостанавливается. Предыдущий метод Fade можно переписать как короутину следующим образом:

IEnumerator Fade()
{
    Color c = renderer.material.color;
    for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
    {
        c.a = alpha;
        renderer.material.color = c;
        yield return null;
    }
}

Эта версия метода выполняет одну итерацию своего цикла for перед приостановкой исполнения в инструкции yield return null. Он возобновляет и выполняет еще одну итерацию цикла в следующем кадре и так далее, делая эффект постепенного исчезновения видимым. Счетчик цикла в методе Fade сохраняет свое правильное значение в течение всего срока жизни сопутствующей программы, и любые переменные или параметры сохраняются между инструкциями yield.

Запуск и остановка сопроцессов

Для запуска сопутствующей программы используйте метод StartCoroutine:

void Update()
{
    if (Input.GetKeyDown("f"))
    {
        StartCoroutine(Fade());
    }
}

Для остановки коррутины используйте StopCoroutine и StopAllCoroutines. Коррутины также останавливаются, если:

  • Значение GameObject.activeSelf становится false для GameObject, к которому прикреплен скрипт.
  • Скрипт MonoBehaviour уничтожается при вызове Destroy.

Примечание: Отключение скрипта MonoBehaviour путем установки enabled на false не останавливает сопутствующие процедуры.

Возобновление сопутствующих программ

Когда приостановленная коррутина возобновляет выполнение зависит от инструкции выхода, предоставленной в yield return заявление. yield return null возобновляется на следующем кадре. Unity имеет набор настраиваемых инструкций по возврату, которые можно использовать для возобновления по истечении указанного времени, при выполнении указанных условий или в определенных точках цикла Player. Дополнительные сведения см. в Ссылка на инструкцию по выходу.

В случае с эффектом fade, вы можете пожелать, чтобы эффект fade происходил с более низкой и более последовательной скоростью, чем частота кадров. Вы можете yield return использовать инструкцию WaitForSeconds для введения фиксированной задержки между итерациями метода Fade следующим образом:

IEnumerator Fade()
{
    Color c = renderer.material.color;
    for (float alpha = 1f; alpha >= 0; alpha -= 0.1f)
    {
        c.a = alpha;
        renderer.material.color = c;
        // Wait for 0.1 seconds before the next iteration
        yield return new WaitForSeconds(.1f);
    }
}

Также можно использовать yield return и Unity Awaitable изнутри сопутствующей программы. Это может быть полезно, если вы хотите интегрировать сопутствующие программы с асинхронным кодом, который использует async и await. Например, в предыдущем примере вы могли бы использовать yield return Awaitable.WaitForSecondsAsync(.1f) вместо yield return new WaitForSeconds(.1f) для достижения того же эффекта.

Важно: Не поддерживается yield return генерический Awaitable<T0> из короутины.

Корутин в режиме редактирования

Соответствующие инструкции инструкции yield во время выполнения находятся в пространстве имен UnityEngine и запускаются в режиме воспроизведения редактора или в автономном платформенном проигрывателе. Они также могут запускаться в режиме редактирования, если ваши скрипты используют атрибуты [ExecuteInEditMode] или [ExecuteAlways], но цикл обновления в режиме редактирования не столь фиксирован и регулярен, как цикл проигрывателя.

Для сопутствующих программ, разработанных специально для запуска в режиме редактирования, используйте Пакет сопутствующих программ редактора.

Коротины в тестах

Unity Test Framework Тесты в режиме воспроизведения, помеченные атрибутом [UnityTest], выполняются как сопутствующие программы и позволяют выводить пользовательские инструкции для Unity Editor из тестов. Дополнительную информацию см. в Инструкции вывода для Редактора.

Производительность коротина

Каждая корроутина создает машину IEnumerator состояние. Частый запуск (например, каждый кадр) выделяет ресурсы и увеличивает нагрузку. yield return null не выделяет ресурсы, но производит инструкции, как new WaitForSeconds. Кэшируйте часто используемые инструкции и избегайте лямбда в WaitUntil и WaitWhile, чтобы предотвратить делегирование и захват выделений.

Предпочитайте долгоживущие сопутствующие процедуры, которые повторяются с yield return null, вместо того, чтобы неоднократно запускать новые. Кэшируйте или объединяйте WaitForSeconds с фиксированными продолжительностями. Сопутствующие процедуры сохраняют ссылки на их владельца и захваченную переменную. Убедитесь, что они заканчиваются или останавливаются с MonoBehaviour.StopCoroutine, чтобы избежать утечек.

Всегда профилируйте, особенно на ограниченных платформах, чтобы подтвердить и найти распределения. Дополнительные сведения см. в Анализ сопутствующих процедур.

Дополнительные ресурсы