Eu entendo o princípio das corotinas. Eu sei como fazer com que o padrão StartCoroutine
/ yield return
padrão funcione em C # no Unity, por exemplo, invoque um método retornando IEnumerator
via StartCoroutine
e nesse método faça alguma coisa, yield return new WaitForSeconds(1);
espere um segundo e faça outra coisa.
Minha pergunta é: o que realmente está acontecendo nos bastidores? O que StartCoroutine
realmente faz? O que IEnumerator
está WaitForSeconds
retornando? Como StartCoroutine
retornar o controle para a parte "outra coisa" do método chamado? Como tudo isso interage com o modelo de simultaneidade do Unity (onde muitas coisas acontecem ao mesmo tempo sem o uso de corotinas)?
IEnumerator
/IEnumerable
(ou os equivalentes genéricos) e que contêm ayield
palavra - chave. Procure iteradores.Respostas:
O link de detalhe em detalhe das rotinas detalhadas do Unity3D está morto. Como é mencionado nos comentários e nas respostas, vou postar o conteúdo do artigo aqui. Este conteúdo vem deste espelho .
fonte
O primeiro cabeçalho abaixo é uma resposta direta à pergunta. Os dois títulos a seguir são mais úteis para o programador diário.
Possivelmente aborrecidos detalhes de implementação de corotinas
As corotinas são explicadas na Wikipedia e em outros lugares. Aqui, fornecerei alguns detalhes do ponto de vista prático.
IEnumerator
,yield
etc. são recursos de linguagem C # usados para um propósito diferente no Unity.Para simplificar,
IEnumerator
alega ter uma coleção de valores que você pode solicitar um por um, como um aList
. No C #, uma função com uma assinatura para retornar umIEnumerator
não precisa realmente criar e retornar um, mas pode permitir que o C # forneça um implícitoIEnumerator
. A função pode fornecer o conteúdo retornadoIEnumerator
no futuro de forma lenta, através deyield return
instruções. Toda vez que o chamador pede outro valor desse implícitoIEnumerator
, a função executa até a próximayield return
instrução, que fornece o próximo valor. Como subproduto disso, a função faz uma pausa até que o próximo valor seja solicitado.No Unity, não os usamos para fornecer valores futuros, exploramos o fato de que a função pausa. Devido a essa exploração, muitas coisas sobre as corotinas no Unity não fazem sentido (o que
IEnumerator
tem a ver com alguma coisa? O que éyield
? Por quenew WaitForSeconds(3)
? Etc.). O que acontece "sob o capô" é que os valores que você fornece por meio do IEnumerator são usadosStartCoroutine()
para decidir quando solicitar o próximo valor, o que determina quando a sua rotina será interrompida novamente.Seu jogo Unity é de thread único (*)
Corotinas não são threads. Há um loop principal do Unity e todas as funções que você escreve são chamadas pelo mesmo thread principal em ordem. Você pode verificar isso colocando um
while(true);
em qualquer uma de suas funções ou corotinas. Isso congelará tudo, até o editor do Unity. Isso é evidência de que tudo é executado em um thread principal. Esse link que Kay mencionou no comentário acima também é um ótimo recurso.(*) O Unity chama suas funções a partir de um segmento. Portanto, a menos que você mesmo crie um thread, o código que você escreveu é único. É claro que o Unity emprega outros tópicos e você pode criar tópicos, se quiser.
Uma descrição prática das corotinas para programadores de jogos
Basicamente, quando você chama
StartCoroutine(MyCoroutine())
, é exatamente como uma chamada de função regular paraMyCoroutine()
, até que o primeiroyield return X
, em queX
é algo comonull
,new WaitForSeconds(3)
,StartCoroutine(AnotherCoroutine())
,break
, etc. Isto é, quando ele começa a diferindo de uma função. O Unity "pausa" essa função exatamente nessayield return X
linha, continua com outros negócios e alguns quadros passam e, quando chega a hora, o Unity retoma essa função logo após essa linha. Ele lembra os valores para todas as variáveis locais na função. Dessa forma, você pode ter umfor
loop que faz loop a cada dois segundos, por exemplo.Quando o Unity retomará a sua rotina depende do que
X
estava na suayield return X
. Por exemplo, se você usouyield return new WaitForSeconds(3);
, ele será retomado após 3 segundos. Se você usouyield return StartCoroutine(AnotherCoroutine())
, o currículo é retomado após aAnotherCoroutine()
conclusão completa, o que permite aninhar comportamentos a tempo. Se você acabou de usar ayield return null;
, ele será retomado no próximo quadro.fonte
Não poderia ser mais simples:
A unidade (e todos os mecanismos de jogo) são baseados em quadros .
A questão toda, toda a razão de ser da Unidade, é que ela é baseada em estruturas. O mecanismo faz as coisas "cada quadro" para você. (Anima, renderiza objetos, faz física e assim por diante.)
Você pode perguntar .. "Oh, isso é ótimo. E se eu quiser que o mecanismo faça algo para mim em cada quadro? Como digo ao mecanismo para fazer isso em um quadro?"
A resposta é ...
É exatamente para isso que serve uma "corotina".
É simples assim.
E considere isso ....
Você conhece a função "Atualizar". Simplesmente, tudo o que você coloca lá é feito em todos os quadros . É literalmente exatamente o mesmo, sem nenhuma diferença, da sintaxe do rendimento da rotina.
Não há absolutamente nenhuma diferença.
Nota de rodapé: como todos apontaram, o Unity simplesmente não tem tópicos . Os "quadros" no Unity ou em qualquer mecanismo de jogo não têm absolutamente nenhuma conexão com os threads de forma alguma.
As rotinas / rendimento são simplesmente como você acessa os quadros no Unity. É isso aí. (E, de fato, é absolutamente igual à função Update () fornecida pelo Unity.) Isso é tudo o que existe, é simples assim.
fonte
Update()
? Quero dizer, deve haver pelo menos uma pequena diferença entre essas duas implementações e seus casos de uso, o que é bastante óbvio.Recentemente, investiguei isso, escreveu um post aqui - http://eppz.eu/blog/understanding-ienumerator-in-unity-3d/ - que esclarece os internos (com exemplos de código densos), a
IEnumerator
interface subjacente , e como é usado para corotinas.fonte
As funções básicas que você obtém automaticamente no Unity são as funções Start () e Update (); portanto, as Coroutine são essencialmente funções como as funções Start () e Update (). Qualquer função antiga func () pode ser chamada da mesma maneira que uma Coroutine pode ser chamada. A unidade obviamente estabeleceu certos limites para as corotinas que as tornam diferentes das funções regulares. Uma diferença é em vez de
Você escreve
para corotinas. E da mesma maneira que você pode controlar o tempo em funções normais com linhas de código como
Uma corotina tem um controle específico sobre como o tempo pode ser controlado.
Embora essa não seja a única coisa possível dentro de um IEnumerator / Coroutine, é uma das coisas úteis para as quais as Coroutines são usadas. Você precisaria pesquisar a API de script do Unity para aprender outros usos específicos das corotinas.
fonte
StartCoroutine é um método para chamar uma função IEnumerator. É semelhante a apenas chamar uma função nula simples, a diferença é que você a usa nas funções IEnumerator. Esse tipo de função é exclusivo, pois permite que você use uma função de rendimento especial ; observe que você deve retornar algo. Isso é tanto quanto eu sei. Aqui eu escrevi um jogo simples de flicker Sobre o método de texto em unidade
Eu então o chamei do próprio IEnumerator
Como você pode ver como eu usei o método StartCoroutine (). Espero ter ajudado de alguma forma. Eu também sou um iniciante; portanto, se você me corrigir ou me apreciar, qualquer tipo de feedback seria ótimo.
fonte