Решил написать маленький тутор по использованию корутин.
В Unity есть набор корутин, позволяющих облегчить разработку последовательно изменяющихся/выполняющихся действий. Большинство из них я опишу ниже. А для начала давайте взглянем на код:
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(); - прерывает выполнение до кадра, в котором обновляется физика.
Специфическое использование:
// Скриншот "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 но без бесконечного цикла:
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());
}
Кода можно применять: например для распределения тяжелых вычислений на несколько кадров, для последовательного изменения чего-то и т.д.
Ну вот и все на сегодня
.