В Unity есть набор корутин, позволяющих облегчить разработку последовательно изменяющихся/выполняющихся действий. Большинство из них я опишу ниже.
А для начала давайте взглянем на код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | using UnityEngine; using System.Collections; public class CorutineTutor : MonoBehaviour { public Texture2D texture; private Vector3 _position; public void Start() { // запускаем корутину StartCoroutine(Coroutine()); } public IEnumerator Coroutine() { // центр экрана Vector3 centerScreen = new Vector3(Screen.width/2f, Screen.height/2f, 0); // бесконечный цикл while (true) { float time = Time.realtimeSinceStartup; // перемещение по "кренделю" :) _position = centerScreen + new Vector3(200 * Mathf.Sin(time), 200 * Mathf.Cos(time), 0) * Mathf.Sin(time / 3); // остановка выполнения функции на 10 миллисекунд yield return new WaitForSeconds(0.01f); } } public void OnGUI() { // рисуем текстуру GUI.DrawTexture( new Rect( _position.x - texture.width / 2f, _position.y - texture.height / 2f, texture.width, texture.height ), texture); } } |
Суть работы кода такова: текстура на экране двигается по фигуре “крендель” с равной скоростью. Ничего особенного, и я даже пример выбрал не особо показательный, но все же продолжу.
Корутина позволяет прерывать вычисления функции и продолжать с того же места, на котором остановились. В моем примере есть функция Coroutine, которая имеет бесконечный цикл, из которого нет выхода. Каждая итерация цикла считает новое положение текстуры на экране и останавливается на 10 мс, перед тем как продолжить. Но загадка в том, что прерывание этой функции происходит не с помощью остановки процесса, а с помощью механизма корутин юнити.
Итак последовательно:
1. При старте скрипта запускается корутина (функция с названием Coroutine).
2. Эта функция выполняется до строчки yield return new WaitForSeconds(0.01f); которая прерывает ее работу на 10 миллисекунд.
3. Прерывание не влияет на остальные функции (процесс не останавливается и действие происходит в том же потоке)
4. По истечении времени корутина продолжает бесконечный цикл пока снова не доходит до строки с задержкой.
5. Функция OnGUI рисует текстуру на экране.
Возможные прерывания выполнения кода:
1. yield return null; – прерывает выполнение корутины до следующего кадра.
2. yield break; завершает выполнение корутины.
3. yield return new WaitForSeconds( количество секунд ); – прерывает на время.
4. yield return new WaitForEndOfFrame(); – прерывает выполнение до конца кадра.
5. yield return new WaitForFixedUpdate(); – прерывает выполнение до кадра, в котором обновляется физика.
Специфическое использование:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Скриншот "Friday's" in Times Square string url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg"; public IEnumerator Start () { // Запуск скачивания картинки по приведенной url WWW www = new WWW (url); // ожидание конца скачивания yield return www; // применение загруженной текстуры к материалу renderer.material.mainTexture = www.texture; } |
Чтобы использовать корутины в C# необходимо объявлять эти функции с типом IEnumerator. Для JavaScript этого не нужно.
Еще один пример как можно реализовать то же самое, что и выше в функции Coroutine но без бесконечного цикла:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public IEnumerator Coroutine() { // центр экрана Vector3 centerScreen = new Vector3(Screen.width/2f, Screen.height/2f, 0); float time = Time.realtimeSinceStartup; // перемещение по "кренделю" :) _position = centerScreen + new Vector3(200 * Mathf.Sin(time), 200 * Mathf.Cos(time), 0) * Mathf.Sin(time / 3); // остановка выполнения функции на 10 миллисекунд yield return new WaitForSeconds(0.01f); // запускаем корутину снова StartCoroutine(Coroutine()); } |
Ну вот и все на сегодня .
2 комментария на «Сопрограммы (Coroutine) в Unity»
Ваш отзыв
Вы должны войти, чтобы оставлять комментарии.
23 Дек 2013 в 15:51
lewisohn@dora.progandist” rel=”nofollow”>.…
спс….
22 Авг 2014 в 23:13
palindromes@abdominis.gainful” rel=”nofollow”>.…
благодарен!!…