Кастомные корутины в Unity 5.3

в 14:09, , рубрики: coroutines, custom coroutines, game development, Gamedev, unity, unity3d, Программирование

Всем привет. Это перевод статьи из официального блога движка Unity. В ней пойдет речь о способе создания своих корутин, появившемся в версии 5.3.

Кастомные корутины в Unity 5.3 - 1

Среди новых блестящих возможностей Unity 5.3 я обнаружил одну небольшую вещь, которая оказалась мне полезной, и, думаю, может пригодиться и вам. Это кастомные корутины, представленные классом CustomYieldInstruction. Благодаря ему, вы сможете очень просто создать свои собственные корутинные yield-операторы. Давайте рассмотрим это на живом примере.

Пример из реальной жизни — исправление ошибки

Недавно я изучал ошибку в элементе пользовательского интерфейса Dropdown, появившемся в Unity 5.2. При установке масштаба времени Time.timeScale в значение 0, Dropdown срабатывал только один раз, после чего он не появлялся снова, пока масштаб времени не устанавливался в какое-нибудь ненулевое значение.

После короткого поиска, мы обнаружили, что проблема возникает в методе Show:

Кастомные корутины в Unity 5.3 - 2
Переменная m_Dropdown не равна null и это препятствует отображению Dropdown

После первого отображения m_Dropdown сворачивается и уничтожается. Да, он должен уничтожаться, но когда Time.timeScale равно нулю, этого не происходит.

Взгляните на метод уничтожения и попробуйте найти проблему:

Кастомные корутины в Unity 5.3 - 3
Благодаря заголовку этой статьи можно догадаться, что проблема в WaitForSeconds. Этот класс использует масштабированное время. Это означает, что когда вы просите WaitForSeconds подождать 1 секунду при масштабе времени равному 0.5, то на самом деле пройдет 2 секунды (1 / 0.5 = 2). Если же масштаб времени равен 0, то придется ждать бесконечно (пока масштаб не станет ненулевым). Dropdown никогда не будет уничтожен после своего первого использования из-за использования нами класса WaitForSeconds.

Решение

Нам нужно реализовать задержку, используя реальное время. Наиболее элегантным подходом будет создание нового yield-оператора — класса WaitForSecondsRealtime. Конечно, если наши собственные разработчики не реализовали WaitForSeconds, используя масштабированное время, то мы должны сообщить им об этом. WaitForSecondsRealtime усилит этот посыл. Нам также нужно обновить документацию для WaitForSeconds, ведь мы нигде не имели ввиду масштабированное время.

Так я и обнаружил класс CustomYieldInstruction, добавленный недавно для создания новых yield-операторов.

Добавить новый оператор очень просто, и это будет решением нашей проблемы:

Кастомные корутины в Unity 5.3 - 4
В любом кастомном yield-операторе нужно переопределить свойство keepWaiting. Если мы хотим, чтобы выполнение программы продолжилось, это свойство должно вернуть false.

Теперь наше исправление ошибки будет выглядеть вот так:

Кастомные корутины в Unity 5.3 - 5
В нашем примере мы берем реальное время и сравниваем его при каждой проверке. Проще и быть не может… хотя, можно сделать и проще при помощи новых yield-операторов WaitUntil и WaitWhile. Используя их, мы можем передать делегат, который будет вызываться для нашей проверки.

Вот альтернативный способ решения проблемы (предположим, что мы просто хотим сделать пятисекундную задержку):

Кастомные корутины в Unity 5.3 - 6
Итак, это была простая, но потенциально широкая возможность. Я считаю, что мораль здесь такова: нужно не забывать читать описания к выпускам версий, ведь в них можно найти новые полезные возможности! А если вам понравились кастомные корутины, взгляните также на UnityEvents — другую мою любимую возможность, которую вы могли пропустить.

Автор: Charoplet

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js