Отладка ошибок ANR

Решение проблем с ANR в вашей игре на Unity — это систематический процесс:

Рисунок 1. Этапы решения ANR в играх Unity.

Интеграция сервисов отчетности

Сервисы отчетности, такие как Android Vitals , Firebase Crashlytics и Backtrace (сертифицированный партнер Unity), обеспечивают регистрацию и анализ ошибок в вашей игре в масштабе. Интегрируйте SDK сервисов отчетности в вашу игру на ранних этапах разработки. Проанализируйте, какой сервис отчетности лучше всего соответствует потребностям вашей игры и бюджету.

Различные сервисы отчетности используют разные способы сбора данных об ошибках. Включите второй сервис отчетности, чтобы повысить вероятность получения достоверных данных для принятия решения об устранении ошибок.

Интеграция SDK для создания отчетов не влияет на производительность игры или размер APK-файла.

Анализ символов

Проанализируйте отчеты вашей службы отчетности и проверьте, находятся ли трассировки стека в удобочитаемом формате. Дополнительную информацию см. в разделах «Сбои Symbolicate Android» и «ANR для игр Unity» .

Рисунок 2. Данные Crashlytics, показывающие идентификатор сборки и отсутствующие символы libil2cpp.so .

Как проверить идентификатор сборки символа

Если система отчетности показывает отсутствие идентификатора сборки, но символы сборки все еще существуют в хранилище сборочной машины, можно проверить идентификатор сборки символов и затем загрузить их в службу отчетности. В противном случае для загрузки файлов символов потребуется новая сборка.

В Windows или macOS:

  1. Перейдите в папку symbols в зависимости от используемой вами системы написания скриптов (см. раздел «Решение» ) :)
    1. Используйте следующую команду (в Windows для запуска утилиты readelf используйте Cygwin ).
    2. Использование команды `grep` необязательно для фильтрации текстового вывода.
    3. Найдите идентификатор сборки (Build ID).
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

Проверьте игровой код

Когда трассировка стека показывает функцию в библиотеке libil2cpp.so , ошибка произошла в коде C#, который был преобразован в C++ . Библиотека libil2cpp.so содержит не только код вашей игры, но и плагины и пакеты.

Имя файла C++ соответствует имени сборки, определенному в проекте Unity. В противном случае имя файла имеет стандартное имя сборки C#. Например, на рисунке 3 показана ошибка в файле Game.cpp (выделено синим), имя которого определено в файле определения сборки. Logger — это имя класса (выделено красным) в скрипте C#, за которым следует имя функции (выделено зеленым). Наконец, — полное имя, сгенерированное конвертером IL2CPP (выделено оранжевым).

Рисунок 3. Стек вызовов тестового проекта из трассировки стека.

Проверьте код вашей игры, выполнив следующие действия:

  • Проверьте проект на C# на наличие подозрительного кода. Обычно необработанные исключения в C# не приводят к ANR или сбою приложения. Тем не менее, убедитесь, что код корректно работает в различных ситуациях. Проверьте, использует ли код сторонний модуль движка, и проанализируйте, не появилась ли эта ошибка в результате недавнего обновления. Кроме того, проверьте, обновляли ли вы Unity недавно или ошибка возникает только на определенных устройствах.
  • Экспортируйте игру как проект Android Studio. Имея полный доступ к преобразованному исходному коду C# вашей игры, вы сможете найти функцию, вызывающую ANR. Код C++ сильно отличается от вашего кода C#, и преобразование кода редко вызывает проблемы. Если вы что-то обнаружите, отправьте запрос в службу поддержки Unity.
  • Просмотрите исходный код игры и убедитесь, что вся логика, выполняющаяся в коллбэках OnApplicationFocus() и OnApplicationPause(), должным образом очищена.
    • В движке Unity используется таймаут для приостановки выполнения; чрезмерная нагрузка на эти коллбэки может привести к ошибке ANR.
    • Добавьте в код фрагменты, содержащие логи или навигационные цепочки, чтобы улучшить анализ данных.
  • Используйте Unity Profiler для анализа производительности игры. Профилирование приложения также может стать отличным способом выявления узких мест, которые могут вызывать ANR (аномальное шумоподавление).
  • Отличный способ выявить длительные операции ввода-вывода в основном потоке — использовать строгий режим .
  • Проанализируйте историю отчетов Android Vitals или другой службы и проверьте версии игры, в которых ошибка возникает чаще всего. Просмотрите исходный код в истории системы контроля версий и сравните изменения кода между релизами. Если вы обнаружите что-то подозрительное, поэкспериментируйте с каждым изменением или потенциальным исправлением по отдельности.
  • Изучите историю сообщений об ошибках ANR в Google Play для устройств и версий Android, получающих наибольшее количество таких сообщений. Если устройства или версии устарели, скорее всего, вы можете смело игнорировать их, если это не повлияет на прибыльность игры. Внимательно изучите данные, поскольку определенная группа пользователей больше не сможет играть в вашу игру. Для получения дополнительной информации см. панель мониторинга распространения .
  • Просмотрите исходный код игры, чтобы убедиться, что вы не вызываете код, который может вызвать проблему, например, вызов метода `finish` может привести к необратимым последствиям, если используется неправильно. Для получения дополнительной информации о разработке под Android обратитесь к руководствам для разработчиков Android.
  • После анализа данных и экспорта сборки игры в Android Studio вы имеете дело с кодом на C и C++, поэтому можете в полной мере использовать инструменты, выходящие за рамки стандартных решений Unity, такие как Android Memory Profiler , Android CPU Profiler и perfetto .

код движка Unity

Чтобы узнать, происходит ли ошибка ANR на стороне движка Unity, проверьте наличие libUnity.so или libMain.so в трассировке стека. Если вы их найдете, выполните следующие действия:

  • Сначала поищите информацию в сообществах ( форумы Unity , обсуждения Unity , Stackoverflow ).
  • Если вы ничего не обнаружите, создайте сообщение об ошибке , чтобы её устранить. Предоставьте трассировку стека в виде символов, чтобы инженеры движка могли лучше понять и исправить ошибку.
  • Проверьте, были ли внесены улучшения в последнюю версию Unity LTS, касающиеся ваших проблем. Если да, обновите игру до этой версии. (Это решение может быть доступно только некоторым разработчикам.)
  • Если в вашем коде используется пользовательская Activity вместо стандартной, проверьте Java-код, чтобы убедиться, что Activity не вызывает никаких проблем.

Сторонний SDK

  • Убедитесь, что все сторонние библиотеки обновлены и не содержат сообщений о сбоях или ошибках ANR для последней версии Android.
  • Зайдите на форумы Unity, чтобы узнать, были ли уже исправлены какие-либо ошибки в более поздних версиях или было ли предложено обходное решение от Unity или от участников сообщества.
  • Проверьте отчет Google Play об ошибках ANR и убедитесь, что Google еще не выявил эту ошибку. Google знает о некоторых ошибках ANR и активно работает над их устранением.

Системная библиотека

Системные библиотеки обычно находятся вне контроля разработчика, но они не составляют значительную часть ошибок ANR. Помимо обращения к разработчику библиотеки или добавления логов для сужения круга проблем, устранить ошибки ANR, связанные с системными библиотеками, довольно сложно.

Причины ухода

ApplicationExitInfo — это API Android для понимания причин ANR (Anti-Resource Node). Если ваша игра использует Unity 6 или более позднюю версию, вы можете вызывать ApplicationExitInfo напрямую. Для более старых версий Unity вам потребуется реализовать собственный плагин, чтобы разрешить вызовы ApplicationExitInfo из Unity.

Crashlytics также использует ApplicationExitInfo ; однако ваша собственная реализация обеспечивает более тонкий контроль и позволяет включать более релевантную информацию .