Depurar ANRs

Resolver ANRs no seu jogo do Unity é um processo sistemático:

Figura 1. Etapas para resolver ANRs em jogos do Unity.

Integrar serviços de relatórios

Os serviços de relatórios, como o Android vitals, o Firebase Crashlytics e o Backtrace (um parceiro certificado para Unity) oferecem registros e análises de erros para seu jogo em escala. Integre os SDKs dos serviços de relatórios ao seu jogo no início do ciclo de desenvolvimento. Analise qual serviço de relatórios atende melhor às necessidades e ao orçamento do seu jogo.

Diferentes serviços de relatórios têm maneiras diferentes de capturar ANRs. Inclua um segundo serviço de relatórios para aumentar a chance de conseguir dados válidos para basear sua decisão de corrigir ANRs.

A integração de SDKs de relatórios não afeta o desempenho do jogo nem o tamanho do APK.

Analisar símbolos

Analise os relatórios do serviço e verifique se os stack traces estão em um formato legível. Consulte Simbolizar falhas do Android e o ANR para jogos Unity para mais informações.

Figura 2. Crashlytics mostrando o ID do build e os símbolos libil2cpp.so ausentes.

Como verificar o ID do build do símbolo

Se o sistema de relatórios mostrar o ID do build ausente, mas os símbolos de build ainda existem no armazenamento da máquina de build, é possível verificar o ID dos símbolos e fazer upload deles para o serviço de relatórios. Caso contrário, será necessário um novo build para fazer upload dos arquivos de símbolo.

No Windows ou macOS:

  1. Navegue até a pasta de símbolos com base no seu back-end de script. Consulte Resolução:
    1. Use o comando a seguir (no Windows, use Cygwin para executar o utilitário readelf).
    2. O uso de grep é opcional para filtrar a saída de texto
    3. Procurar o ID do build
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

Inspecionar código do jogo

Quando o stack trace mostra uma função na biblioteca libil2cpp.so, o erro ocorreu no código C#, que é convertido em C++. A biblioteca libil2cpp.so não tem apenas o código do seu jogo, mas também plug-ins e pacotes.

O nome do arquivo C++ segue o nome da Assembly definido no projeto do Unity. Caso contrário, o nome do arquivo será o Assembly-C# padrão. Por exemplo, a Figura 3 mostra o erro no arquivo Game.cpp (destacado em azul), que é o nome definido no arquivo de definição do Assembly. Logger é o nome da classe (destacado em vermelho) no script C#, seguido pelo nome da função (destacado em verde). Por fim, o nome completo gerado pelo conversor IL2CPP (destacado em laranja).

Figura 3. Testar a pilha de chamadas do projeto no Backtrace.

Inspecione o código do jogo fazendo o seguinte:

  • Examine o projeto C# em busca de códigos suspeitos. Normalmente, exceções não processadas de C# não causam um ANR nem uma falha de app. Mesmo assim, verifique se o código é executado corretamente em diferentes situações. Confira se o código usa um módulo de mecanismo de terceiros e analise se uma versão recente introduziu o erro. Além disso, confira se você atualizou recentemente o Unity ou se o erro ocorre apenas em dispositivos específicos.
  • Exporte o jogo como um projeto do Android Studio. Com acesso total ao código-fonte convertido em C# do jogo, você poderá encontrar a função que está causando o ANR. O código C++ é muito diferente do seu código C#, e a conversão do código raramente tem um problema. Se encontrar algo, abra um tíquete de suporte no Unity.
  • Revise o código-fonte do jogo e limpe as lógicas dos callbacks OnApplicationFocus() e OnApplicationPause().
    • O mecanismo do Unity tem um tempo limite para pausar a execução. O excesso de carga de trabalho nesses callbacks pode causar um ANR.
    • Adicione registros ou navegação estrutural a partes do código para aprimorar a análise de dados.
  • Use o Unity Profiler para investigar o desempenho do jogo. A criação de perfil no app também pode ser uma ótima maneira de identificar gargalos que possam estar causando o ANR.
  • Uma ótima maneira de identificar operações de E/S longas na linha de execução principal é usar o modo restrito.
  • Analise o Android vitals ou outro histórico do serviço de relatórios e verifique as versões de lançamento do jogo em que o erro mais ocorre. Revise o código-fonte no histórico de controle de versões e compare as mudanças de código entre as versões. Se você encontrar algo suspeito, teste cada mudança ou possível correção individualmente.
  • Analise o histórico de relatórios de ANR do Google Play para os dispositivos e as versões do Android que recebem mais ANRs. Se os dispositivos ou as versões estiverem desatualizados, você poderá ignorá-los com segurança, caso isso não afete a lucratividade do jogo. Estude os dados com atenção, porque um grupo específico de usuários não poderá mais jogar. Para mais informações, consulte Painel de distribuição.
  • Revise o código-fonte do jogo para garantir que você não esteja chamando nenhum código que possa causar um problema. Por exemplo, finish pode ser destrutivo se não for usado corretamente. Consulte os guias do desenvolvedor Android para saber mais sobre o desenvolvimento em Android.
  • Depois de analisar os dados e exportar o build do jogo para o Android Studio, você vai trabalhar com código C e C++ e aproveitar ao máximo as ferramentas além das soluções padrão do Unity, como Android Memory Profiler, Android CPU Profiler e perfetto.

Código do mecanismo do Unity

Para saber se um ANR está acontecendo no mecanismo do Unity, verifique se há libUnity.so ou libMain.so nos stack traces. Se eles forem encontrados, siga estas etapas:

  • Primeiro, pesquise os canais da comunidade (Fóruns, Unity Discussions, Stack Overflow).
  • Se você não encontrar nada, registre um bug para resolver o problema. Forneça um stack trace simbolizado para que os engenheiros do mecanismo possam entender e resolver melhor o erro.
  • Verifique se o LTS do Unity mais recente fez melhorias relacionadas aos seus problemas. Se esse for o caso, faça upgrade do jogo para usar essa versão. Essa solução pode ser possível apenas para alguns desenvolvedores.
  • Caso seu código use um Activity personalizado em vez do padrão, revise o código Java para garantir que a atividade não esteja causando problemas.

SDK de terceiros

  • Confira se todas as bibliotecas de terceiros estão atualizadas e não têm relatórios de falhas ou ANRs para a versão mais recente do Android.
  • Acesse os Fóruns do Unity para ver se algum erro já foi resolvido em uma versão mais recente ou se uma solução alternativa foi fornecida pelo Unity ou por um membro da comunidade.
  • Analise o Relatório de ANR do Google Play e verifique se o erro ainda não foi identificado pelo Google. O Google está ciente de alguns ANRs e está trabalhando para corrigi-los.

Biblioteca do sistema

As bibliotecas do sistema geralmente estão longe do controle do desenvolvedor, mas não representam uma porcentagem significativa dos ANRs. Além de entrar em contato com o desenvolvedor da biblioteca ou adicionar registros para restringir o problema, os ANRs da biblioteca do sistema são difíceis de resolver.

Motivos de saída

ApplicationExitInfo é uma API do Android para entender as causas de ANR. Se o jogo estiver usando o Unity 6 ou mais recente, chame ApplicationExitInfo diretamente. Para versões mais antigas do Unity, é necessário implementar seu próprio plug-in para ativar chamadas ApplicationExitInfo do Unity.

O Crashlytics também usa ApplicationExitInfo. No entanto, sua própria implementação oferece um controle mais preciso e permite incluir informações mais relevantes.