Depurar ANRs

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

Figura 1. Etapas para resolver erros ANR em jogos do Unity.

Integrar serviços de relatórios

Serviços de relatórios como Android vitals, Firebase Crashlytics e Backtrace (um parceiro certificado da Unity ) oferecem registro e análise de erros para seu jogo em grande escala. Integre os SDKs de serviços de relatórios ao jogo no início do ciclo de desenvolvimento. Analise qual serviço de relatórios é mais adequado às necessidades e ao orçamento do seu jogo.

Cada serviço de geração de relatórios tem uma maneira diferente de capturar ANRs. Inclua um segundo serviço de relatórios para aumentar a chance de obter dados válidos que ajudem na 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 seu serviço de relatórios e verifique se os rastreamentos de pilha estão em um formato legível. Consulte Simbolizar falhas do Android e o erro ANR para jogos Unity para mais informações.

Figura 2. O Crashlytics mostra o ID da build e os símbolos libil2cpp.so ausentes.

Como verificar o ID de build do símbolo

Se o sistema de relatórios mostrar o ID de build ausente, mas os símbolos ainda existirem 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 fazer um novo build para enviar os arquivos de símbolos.

No Windows ou macOS:

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

Inspecionar o código do jogo

Quando o rastreamento de pilha mostra uma função na biblioteca libil2cpp.so, o erro aconteceu no código C#, que é convertido para C++. A biblioteca libil2cpp.so tem não apenas o código do jogo, mas também plug-ins e pacotes.

O nome do arquivo C++ segue o nome do assembly definido no projeto Unity. Caso contrário, o nome do arquivo terá o nome padrão Assembly-C#. Por exemplo, a figura 3 mostra o erro no arquivo Game.cpp (destacado em azul), que é o nome definido no arquivo de definição de 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 que o conversor IL2CPP gerou (destacado em laranja).

Figura 3. Pilha de chamadas do projeto de teste do Backtrace.

Inspecione o código do jogo fazendo o seguinte:

  • Examine o projeto C# para verificar se há código suspeito. Normalmente, exceções não processadas em C# não causam um ANR ou falha no aplicativo. Mesmo assim, verifique se o código é executado corretamente em diferentes situações. Verifique 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, verifique se você atualizou o Unity recentemente ou se o erro só acontece em dispositivos específicos.
  • Exporte o jogo como um projeto do Android Studio. Com acesso completo ao código-fonte C# convertido do jogo, você pode encontrar a função que está causando o ANR. O código C++ é muito diferente do código C#, e a conversão raramente tem um problema. Se você encontrar algo, abra um tíquete de suporte para a Unity.
  • Revise o código-fonte do jogo e verifique se toda a lógica em execução nos callbacks OnApplicationFocus() e OnApplicationPause() foi limpa corretamente.
    • 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 rastros a partes do código para melhorar a análise de dados.
  • Use o Unity Profiler (link em inglês) para investigar o desempenho do jogo. A criação de perfil do app também pode ser uma ótima maneira de identificar gargalos que podem 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 histórico do Android Vitals ou de outro serviço de relatórios e verifique as versões de lançamento do jogo em que o erro ocorre com mais frequência. Revise seu código-fonte no histórico de controle de versão e compare as mudanças 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 versões do Android que recebem mais ANRs. Se os dispositivos ou versões estiverem desatualizados, é possível ignorá-los com segurança se isso não afetar a lucratividade do jogo. Analise os dados com cuidado, já que um grupo específico de usuários não poderá mais jogar. Para mais informações, consulte Painel de distribuição.
  • Analise o código-fonte do jogo para garantir que você não está chamando nenhum código que possa causar um problema. Por exemplo, finish pode ser destrutivo se não for usado corretamente. Consulte os guias para desenvolvedores Android e saiba mais sobre o desenvolvimento no 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++. Assim, é possível aproveitar ao máximo ferramentas além das soluções padrão do Unity, como o Android Memory Profiler, o Android CPU Profiler e o perfetto.

Código do mecanismo Unity

Para saber se um ANR está acontecendo no lado do mecanismo Unity, verifique se há libUnity.so ou libMain.so nos rastreamentos de pilha. Se você encontrar, siga estas etapas:

  • Primeiro, pesquise nos canais da comunidade (Fóruns do Unity, Discussões do Unity, Stackoverflow).
  • Se você não encontrar nada, informe um bug para resolver o problema. Forneça um rastreamento de pilha simbolizado para que os engenheiros do mecanismo possam entender e resolver melhor o erro.
  • Verifique se a LTS do Unity mais recente fez melhorias relacionadas aos seus problemas. Se for o caso, faça upgrade do jogo para usar essa versão. Essa solução só é possível para alguns desenvolvedores.
  • Se o código usar 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

  • Verifique se todas as bibliotecas de terceiros estão atualizadas e não têm relatórios de falhas ou ANRs na versão mais recente do Android.
  • Acesse os fóruns do Unity para saber 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 já foi identificado pelo Google. O Google está ciente de alguns ANRs e trabalhando ativamente 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 de 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

O ApplicationExitInfo é uma API do Android para entender as causas de ANR. Se o jogo estiver usando o Unity 6 ou uma versão 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 o ApplicationExitInfo, mas sua própria implementação oferece um controle mais preciso e permite incluir informações mais relevantes.