2016-08-14 3 views
2

Я очень новичок в программировании, и у меня такое ощущение, что здесь есть очень глупая ошибка. Но может ли кто-нибудь объяснить мне, почему вместо 4 сообщений с задержкой в ​​2 секунды между ними я мгновенно получаю только последнее сообщение.Почему моя «доходность» не работает?

using UnityEngine; 
using System.Collections.Generic; 
using System.Collections; 
using System.Linq; 
using UnityEngine.UI; 

public class Wait : MonoBehaviour { 

    private int i = 0; 
    public string[] message; 

    [SerializeField] 
    private Text toText; 

    public IEnumerator Message(float waitTime) 
    { 
     toText.text = message[i]; 
     i++; 
     yield return new WaitForSeconds(waitTime = 2f); 
    } 

    void Start() 
    { 
     StartCoroutine(Message(i)); 
     StartCoroutine(Message(i)); 
     StartCoroutine(Message(i)); 
     StartCoroutine(Message(i)); 
    } 
} 
+1

Ключевое слово делает ваш метод отложенным. Таким образом, он выполняется только при вызове 'Enumerator.MoveNext()', который вы никогда не вызываете (для этого используйте, например, 'for'-loop). – HimBromBeere

+0

@HimBromBeere не то, что работа 'StartCoroutine'? –

ответ

0
void Start() 
{ 
    StartCoroutine(Message(i)); 
    StartCoroutine(Message(i)); 
    StartCoroutine(Message(i)); 
    StartCoroutine(Message(i)); 
} 

Я не думаю, что это делает то, что вы считаете нужным. Это не будет ждать завершения каждого StartCoroutine и вызовет следующий StartCoroutine.

Это то, что происходит:

Первый StartCoroutine(Message(i)); вызов будет запустить функцию Message. После того, как он встретит строку кода yield return new WaitForSeconds(waitTime = 2f);, он затем перепрыгнет обратно в функцию Start().

Следующий StartCoroutine(Message(i)); будет называться тогда, то же самое произойдет снова.

При вызове сопрограммы функции из не функций сопрограммных, до тех пор, пока у вас есть yield return new WaitForSeconds, yield return null; или yield return каких-либо YieldInstruction реализован, исполнение возвращается к ней, не функциям сопрограммных в-котором функция StartCoroutine была вызвана от и продолжать выполнять другой код.

Чтобы заставить coroutine подождать, пока другой закончит, сделайте вызов функции StartCoroutine(Message(i)); другой функцией сопрограмм. Это позволит вам вызывать yield каждый вызов функции coroutine. Это называется цепочкой coroutine.

Для цепи или yield вызов функции сопрограммы, просто введите yield return перед функцией StartCoroutine. yield return StartCoroutine(Message(i));

public class Wait : MonoBehaviour { 
    private int i = 0; 
    public string[] message; 

    [SerializeField] 
    private Text toText; 

    public IEnumerator Message(float waitTime) 
    { 
     // toText.text = message[i]; 
     i++; 
     yield return new WaitForSeconds(waitTime = 2f); 
    } 

    void Start() 
    { 
     StartCoroutine(startMessage()); 
    } 

    IEnumerator startMessage() 
    { 
     yield return StartCoroutine(Message(i));//Wait until this coroutine function retuns 
     yield return StartCoroutine(Message(i));//Wait until this coroutine function retuns 
     yield return StartCoroutine(Message(i));//Wait until this coroutine function retuns 
     yield return StartCoroutine(Message(i));//Wait until this coroutine function retuns 
    } 
} 

Теперь каждый StartCoroutine(Message(i)); вызов будет ждать, пока первый не закончит. Вы можете всегда использовать переменную boolean, чтобы сделать это, но гораздо лучше, чтобы yield вызов StartCoroutine.

0

Причина текст устанавливается мгновенно, потому что StartCoroutine выполнит нумератор от Message.

Первые две вещи, которые происходят, это установка текста и увеличение i. Только после этого вы получите WaitForSeconds. Именно в этот момент StartCoroutine приостановит дальнейшее выполнение Message.

Если у вас была линия после yield return, вы бы увидели последствия этого после 2 секунд.

в примере в документации вы можете также увидеть поведение после yield return Wait https://docs.unity3d.com/ScriptReference/MonoBehaviour.StartCoroutine.html

Я предложил бы запустить следующий тест, чтобы стать более знакомы с тем, как обратный выход работает:

IEnumerator MessageOuter() { 
    Console.WriteLine("outer 1"); 
    var inner = MessageInner(); 
    Console.WriteLine("outer 2"); 
    return inner; 
} 
IEnumerator MessageInner() { 
    Console.WriteLine("inner 1"); 
    yield return new WaitForSeconds(1); 
    Console.WriteLine("inner 2"); 
    yield return new WaitForSeconds(1); 
    Console.WriteLine("inner 3"); 
} 
void Start() { 
    Console.WriteLine("start 1"); 
    var outer = MessageOuter(); 
    Console.WriteLine("start 2"); 
    StartCoroutine(outer); 
    Console.WriteLine("start 3"); 
} 
Смежные вопросы