Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   www.boolean.name > Программирование игр для компьютеров > Unity > Уроки

Ответ
 
Опции темы
Старый 10.09.2010, 18:46   #1
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,505
Написано 2,960 полезных сообщений
(для 5,242 пользователей)
Сопрограммы (Coroutine) в Unity

Решил написать маленький тутор по использованию корутин.

В 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/2fScreen.height/2f0);

        
// бесконечный цикл
        
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.texture.width 2f
                
_position.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/2fScreen.height/2f0);

        
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());
    } 

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

Ну вот и все на сегодня .
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Эти 7 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
den (12.09.2010), HolyDel (11.09.2010), Igor (17.12.2014), Illidan (11.09.2010), Mr_F_ (11.09.2010), Nuprahtor (10.09.2010), Taugeshtu (10.09.2010)
Старый 17.12.2014, 22:30   #2
LLI.T.A.L.K.E.R.
Мастер
 
Аватар для LLI.T.A.L.K.E.R.
 
Регистрация: 24.06.2009
Адрес: Набережные Челны
Сообщений: 930
Написано 292 полезных сообщений
(для 504 пользователей)
Ответ: Сопрограммы (Coroutine) в Unity

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


void Start() {
StartCoroutine("AimCoroutine");
StartCoroutine(SpawnCoroutine());
}

IEnumerator AimCoroutine() {
while(true)
{
yield return new WaitForSeconds(0.1f);
//некий код
StopCoroutine("AimCoroutine"); //короутин сам себя прекратит, если нужно одноразовое использование
}
}

IEnumerator SpawnCoroutine() {
while(true)
{
yield return new WaitForSeconds(3.0f-speed);
//некий код
StopCoroutine(SpawnCoroutine); //либо StopCoroutine(SpawnCoroutine())
//тут уже не получится самопрекратить короутин (у меня Unity ругался поэтому я пишу названия в двойный кавычках)
}
}

если сможете, то можете поправить и указать причину ошибки StopCoroutine(SpawnCoroutine())
(Offline)
 
Ответить с цитированием
Старый 17.12.2014, 22:36   #3
Mr_F_
Терабайт исходников
 
Аватар для Mr_F_
 
Регистрация: 13.09.2008
Сообщений: 3,907
Написано 2,157 полезных сообщений
(для 5,843 пользователей)
Ответ: Сопрограммы (Coroutine) в Unity

while(true)
{
yield return new WaitForSeconds(0.1f);
//некий код
StopCoroutine("AimCoroutine"); //короутин сам себя прекратит, если нужно одноразовое использование
}
почему не сделать просто break?
__________________
бложик | geom.io | твиттер | faded | демо 1 2 | роботы | лайтмаппер
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
LLI.T.A.L.K.E.R. (17.12.2014)
Старый 17.12.2014, 22:46   #4
LLI.T.A.L.K.E.R.
Мастер
 
Аватар для LLI.T.A.L.K.E.R.
 
Регистрация: 24.06.2009
Адрес: Набережные Челны
Сообщений: 930
Написано 292 полезных сообщений
(для 504 пользователей)
Ответ: Сопрограммы (Coroutine) в Unity

всех нюансов ещё не знаю

теперь нашёл
Возможные прерывания выполнения кода:

но в коде не видел...

и уточню - почему не сделать просто: yield break;
а то уже хотел: break; писать =)
(Offline)
 
Ответить с цитированием
Старый 18.12.2014, 04:26   #5
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,505
Написано 2,960 полезных сообщений
(для 5,242 пользователей)
Ответ: Сопрограммы (Coroutine) в Unity

Тут вот третий пост показывает, как остановить корутину, которая принимает IEnumerator:
http://forum.unity3d.com/threads/how...erator.249732/

// variable that holds reference to coroutine (IEnumerator)
public IEnumerator routine;
 
// get IEnumerator from Coroutine and start
routine DoWork();
StartCoroutineroutine );
 
// stop Coroutine
StopCoroutineroutine ); 
т.е. надо сохранить в публичной переменной ссылку на созданный первым запуском IEnumerator. Единственное я вижу в этом проблему: корутина сработает при запуске два раза, надо в начало ставить yield return null; наверное...
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
LLI.T.A.L.K.E.R. (18.12.2014)
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +1, время: 05:50.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com