2015-04-13 3 views
1

Я работаю в Unity, но это действительно просто вопрос C#, поэтому я надеюсь, что это правильный раздел, чтобы опубликовать это. В любом случае, у меня все еще есть проблемы с визуализацией исполнения скриптов в моей голове, особенно когда есть более одного запуска, и все они имеют разные функции.Понимание выполнения Coroutines

В последнее время это осложнилось, так как я добавил Update, FixedUpdate и Coroutine в список «Когда это работает»? Обновление и исправление обновления. Я получаю суть.

Что касается Coroutine, я в основном понимаю, что это функция, которая дает мне более точный контроль времени. Это единственный способ, которым я знаю, что могу сделать «return return new WaitForSeconds (i)»;

Мой вопрос больше о порядке их исполнения. Например, если я вызываю coroutine из update (который выполняется один раз для фрейма), а у coroutine есть waitforseconds (10), то приостанавливает выполнение всего скрипта? Есть ли что-то вроде одного центрального такта? Будет ли обновление работать снова до тех пор, пока ожидание не закончится? Что делать, если у меня есть еще один скрипт с функцией обновления, в которой также присутствует другая сопрограмма, и оба запускаются одновременно?

Возможно, я расстроен. Сложно объяснить. Я прочитал пару информационных материалов в Интернете о сопрограмме, но ничего, что действительно объясняет это, я не могу ее визуализировать.

+1

Это остановит эту конкретную рутину, и больше ничего. –

+0

Так как эта процедура приостанавливается, будут ли какие-либо строки добавлены после продолжения работы «statcoroutine»? –

+0

Другие сопрограммы будут работать независимо от приостановленного. –

ответ

5

Первое, что вам нужно знать, это то, что функции, которые используют ключевое слово yield и возвращают IEnumerable, превращаются в итераторы. Это синтаксический сахар для написания класса, который реализует IEnumerator.

Они, как правило, используется в сочетании с foreach петлями:

IEnumerable<string> GetFruits() 
{ 
    yield return "Apple"; 
    yield return "Pear"; 
} 

foreach (string fruit in GetFruits()) 
    Console.WriteLine(fruit); 

Что здесь происходит, что GetFruits возвращает объект генератора, который реализует IEnumerator<string>. Его метод MoveNext выполняет часть исходного кода GetFruits каждый раз, когда он вызывается. Каждый вызов выполняет код до следующего оператора yield и использует «возвращаемое значение» этого yield для установки свойства Current генератора.

Результаты В foreach цикл в коде, который вызывает MoveNext и которая хранит Current в переменной цикла, что делает итерации гораздо более удобным для чтения, что-то вроде следующего:

IEnumerator<string> fruitsGenerator = GetFruits().GetEnumerator(); 
while (fruitsGenerator.MoveNext()) 
{ 
    string fruit = fruitsGenerator.Current; 
    Console.WriteLine(fruit); 
} 

Но вы не ограничены использованием итераторов в петлях. Вы можете сохранить ссылку на генератор и вызвать его метод MoveNext, скажем, один раз в секунду. Или всякий раз, когда пользователь нажимает кнопку. Или вы можете использовать значение Current, чтобы определить, нужно ли снова звонить MoveNext.

И это именно то, что делает Unity. Командная строка по существу является объектом-генератором (с некоторой дополнительной информацией, например, сколько времени осталось до тех пор, пока она не будет вызвана снова). Когда coroutine дает объект WaitForSeconds, Unity обновляет время ожидания этой сопрограммы и не будет называть этот метод coroutine MoveNext еще до истечения времени ожидания.

Каждый цикл обновления, Unity вызывает Update на ваших игровых объектах и ​​MoveNext на ваших сопрограммах, если сопрограмма еще не находится в состоянии ожидания. Ожидается, что сопрограммы, которые ждут, просто пропущены - он не блокирует какой-либо другой код.

+0

bravo mr pieter upvoted и, возможно, я предлагаю одну штуку noob, которую я использую с совместными подпрограммами, используйте bool, как это public bool runOnce = false; void Update() { if (! RunOnce) {StartCourotine (FunctionName()); runOnce = true; } } Таким образом, сопрограмма запускается только один раз, и вы можете использовать bool для запуска, когда захотите. Да, не обязательно, а не лучше, но я думал, что это даст вам новые идеи. – LumbusterTick

Смежные вопросы