Pergunta

Recebi esse método (dentro de um script de unidade C#), mas não entendo como a parte "rendimento" realmente funciona.

Sei do MSDN que a função retornará um ienumerator que eu poderia iterar, mas esse código aguarda 1,5 segundos e não é iterado porque isso significaria que os objetos criados no interior foram criados várias vezes. Alguém aqui que pode me explicar como esse código funciona?

IEnumerator DestroyShip()
{
    // create new gameobject
    Instantiate(ExplosionPrefab, transform.position, transform.rotation);
    // make current gameobject invisible
    gameObject.renderer.enabled = false;
    // set new position for the current gameobject
    transform.position = new Vector3(0f, transform.position.y, transform.position.z);
    // wait for 1,5 seconds 
    yield return new WaitForSeconds(1.5f);
    // make the current gameobject visible again
    gameObject.renderer.enabled = true;
}
Foi útil?

Solução

O enumerador que o compilador gera para você está sendo iterado. Uma vez.

O compilador gerará uma classe que implementa o iEnumerator, que possui uma função moveNeNext () e uma propriedade atual. A classe terá todos os membros necessários para armazenar o estado da função entre as chamadas. Os detalhes exatos podem ser considerados "mágica do compilador".

O objetivo desta classe gerado será tratado e gerenciado pelo mecanismo Unity3D. O mecanismo Unity3D ligará para o MoveNeNext () em cada coroutina ativa uma vez cada quadro (a menos que seja instruído de outra forma).

Isso permitiu que o programador Unity3D escrevesse scripts que são reproduzidos um quadro de cada vez. Uma combinação de mágica do compilador C# e a mágica do motor Unity3D resulta em scripts muito poderosos, mas fáceis de usar.

Para responder à sua pergunta: o código em sua função será executado uma vez, mas será uma pausa na instrução 'rendimento de rendimento'.

Como afirmado acima, um objeto especial que implementa o iEnumerator é criado pelo compilador C#.

Na primeira chamada para MoveNeNext (), sua função cria uma explosão e define o objeto atual para "New WaitForSeconds (1.5F)".

O mecanismo Unity3D inspeciona esse objeto, vê que é uma instância da classe especial "WaitForSeconds", então coloca o enumerador em alguma fila de espera e não solicitará o segundo elemento até que 1,5 segundos foram aprovados. Enquanto isso, muitos quadros serão renderizados e a explosão será tocada.

Após 1,5 segundos, a unidade antecederá o enumerador da fila e chamará o Movenext () novamente. A segunda parte da sua função será executada agora, mas deixará de gerar um segundo objeto. O MoveNeNext () retornará false para indicar que não conseguiu obter um novo elemento, que é o sinal para o Unity3D para jogar esse enumerador fora. O coletor de lixo recuperará a memória em algum momento.

Como dito: muito compilador e magia do Unity3D estão acontecendo. Desde que você se lembre de que sua função será suspensa até o próximo quadro em cada declaração de retorno de rendimento, você saberá o suficiente para se beneficiar dessas funções especiais.

Outras dicas

Se yield é usado uma vez, é como se você estivesse retornando um ienumerador com um elemento, é por isso que você tem a impressão de que ele não itera.

É um uso bastante estranho da palavra -chave de rendimento, é difícil entender por que ela foi implementada, sem ver todo o contexto.

É melhor voltar IEnumerable ao invés de IEnumerator como é mais chamativo e fácil de usar. É ainda melhor usar IEnumerable<T>. O retorno do rendimento é apenas açúcar sintático para implementar um bloco de iterador, o compilador gera o código relevante, pois é essencialmente a placa de caldeira padrão que pode ser facilmente gerada programaticamente. Você geralmente usa o rendimento de rendimento quando deseja fazer uma série de ações únicas em repouso como uma coleção, por exemplo:

public IEnumerable<Thing> GetThings()
{
    yield return GetNextThing();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top