Devo usar Async & Await, em vez de Coroutines, no Unity?

Aug 18 2020

Devo usar Async & Await no Unity? Ou devo continuar usando corrotinas? Se eu devo usar Async & Await, como posso fazer isso de maneira comparável às Coroutines?

Respostas

2 Kevin Aug 19 2020 at 01:04

Em contraste com a resposta de Evorlor, aqui estão algumas boas razões para usar corrotinas:

  • Eles têm sido a solução padrão no Unity por muitos anos e qualquer outra pessoa que você traga para a equipe já deve estar confortável com eles.
  • Eles estão em sintonia com o motor. WaitForFixedUpdate()garante que a próxima etapa na corrotina será executada durante o ciclo de atualização fixa. WaitForEndOfFrame()garante que a próxima etapa será executada no ciclo de atualização. Se você usar async / await do C #, não há como garantir que seja complicado garantir que o código permaneça em sintonia com o mecanismo (consulte os comentários).
  • Da mesma forma, WaitForSeconds()leva Time.timeScaleem consideração a corrente , algo que não é possível await.
  • As corrotinas são interrompidas automaticamente quando o objeto que as está executando é destruído ou desabilitado (isso é ocasionalmente indesejável, caso em que você pode querer assíncrono / aguardar).

Outra nota: Evorlor sugeriu esta solução para esperar por uma condição:

//Wait until condition has been met
while (!ConditionMet())
{
    yield return new WaitForEndOfFrame();
    Debug.Log("Condition has been met.");
}

Isso é comum, mas não é a solução pretendida para esperar por uma condição. A solução pretendida tem menos clichê (e possivelmente menos sobrecarga de CPU):

yield return new WaitUntil(() => ConditionMet());

Quando não devo usar corrotinas?

  • Quando você deseja que uma função semelhante a uma co-rotina retorne um valor (consulte esta postagem do blog recomendada por DMGregory)
  • Se você estiver tendo problemas para fazer com que o tratamento de erros funcione com sua co-rotina (consulte a postagem do blog do marcador anterior. Observe que você pode colocar um bloco try-catch em uma co-rotina, desde que esse bloco não inclua uma instrução de "rendimento") .
  • Se você fez o perfil de sua aplicação e descobriu que as corrotinas estão custando uma sobrecarga de desempenho que você não pode dispensar e isso não pode ser corrigido otimizando suas corrotinas (improvável para a maioria dos jogos)
  • Se você precisa executar uma função semelhante a co-rotina de uma classe C # regular que não estende MonoBehaviour
  • Se você precisar de uma função semelhante a uma co-rotina para continuar em execução quando seu GameObject for destruído ou desativado.
  • Ao trabalhar com uma biblioteca que faz uso intenso async(por exemplo, Google Firebase)
  • Quando seu código precisa ser paralelo (multi-thread). Embora possam ser usados ​​para melhorar o desempenho, distribuindo uma operação cara por vários quadros, as corrotinas não são rosqueadas . Quando você precisar de código multi-thread para desempenho máximo, use Threads C # ou o Unity Job System.
  • Se você tiver qualquer outro bom motivo para não usar corrotinas

Na minha experiência, todas essas exceções são muito raras e normalmente você não precisa considerá-las. YMMV dependendo do projeto e seu estilo de codificação.