Unity ゲームで ANR を解決するには、体系的なプロセスが必要です。

レポート サービスを統合する
Android Vitals、Firebase Crashlytics、Backtrace(Unity の認定パートナー)などのレポート サービスは、ゲームのエラーログと分析を大規模に提供します。開発サイクルの早い段階で、レポート サービス SDK をゲームに統合します。ゲームのニーズと予算に最適なレポート サービスを分析します。
レポート サービスによって、ANR のキャプチャ方法が異なります。2 つ目のレポート サービスを含めて、ANR の修正に関する意思決定をサポートする有効なデータを取得できる可能性を高めます。
レポート SDK を統合しても、ゲームのパフォーマンスや APK のサイズに影響はありません。
シンボルを分析する
レポート サービスからレポートを分析し、スタック トレースが人が読める形式になっているかどうかを確認します。詳しくは、Unity ゲームの Android のクラッシュと ANR をシンボリケートするをご覧ください。

libil2cpp.so
記号が欠落している。シンボル ビルド ID を確認する方法
レポート システムにビルド ID が見つからないと表示されても、ビルド シンボルがビルドマシンのストレージにまだ存在する場合は、シンボルのビルド ID を確認してから、レポート サービスにアップロードできます。それ以外の場合は、シンボル ファイルをアップロードするために新しいビルドが必要です。
Windows または macOS の場合:
- スクリプト バックエンドに基づいてシンボル フォルダに移動します(解決策を参照)。
- 次のコマンドを使用します(Windows では、Cygwin を使用して
readelf
ユーティリティを実行します)。 - テキスト出力をフィルタするために grep を使用することは省略可能です
- ビルド ID を探す
- 次のコマンドを使用します(Windows では、Cygwin を使用して
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95
ゲームコードを検査する
スタック トレースに libil2cpp.so
ライブラリの関数が表示されている場合、エラーは C++ に変換された C# コードで発生しています。libil2cpp.so
ライブラリには、ゲームコードだけでなく、プラグインやパッケージも含まれています。
C++ ファイル名は、Unity プロジェクトで定義されたアセンブリ名に従います。それ以外の場合、ファイル名にはデフォルトのアセンブリ C# 名が使用されます。たとえば、図 3 は、アセンブリ定義ファイルで定義された名前であるファイル Game.cpp
(青でハイライト表示)のエラーを示しています。Logger
は、C# スクリプトのクラス名(赤でハイライト表示)の後に、関数名(緑でハイライト表示)が続きます。Finally は、IL2CPP コンバータが生成したフルネームです(オレンジ色でハイライト表示されています)。

次の手順でゲームコードを検査します。
- C# プロジェクトで不審なコードがないか調べます。通常、C# の未処理の例外は ANR やアプリのクラッシュを引き起こしません。それでも、さまざまな状況でコードが適切に実行されるようにしてください。コードがサードパーティ エンジン モジュールを使用しているかどうかを確認し、最近のリリースでエラーが発生したかどうかを分析します。また、最近 Unity を更新したかどうか、エラーが特定のデバイスでのみ発生するかどうかを確認します。
- ゲームを Android Studio プロジェクトとしてエクスポートします。変換されたゲームの C# ソースコードに完全にアクセスできるため、ANR の原因となっている関数を見つけることができます。C++ コードは C# コードとは大きく異なり、コード変換で問題が発生することはほとんどありません。何か見つかった場合は、Unity にサポート チケットを提出してください。
- ゲームのソースコードを確認し、OnApplicationFocus() コールバックと OnApplicationPause() コールバックで実行されるロジックが適切にクリーンアップされていることを確認します。
- Unity エンジンには実行を一時停止するタイムアウトがあります。これらのコールバックで過度のワークロードが発生すると、ANR が発生する可能性があります。
- コードの一部にログやブレッドクラムを追加して、データ分析を強化します。
- Unity Profiler を使用して、ゲームのパフォーマンスを調査します。アプリのプロファイリングは、ANR の原因となっている可能性のあるボトルネックを特定するうえでも役立ちます。
- メインスレッドで長い I/O オペレーションを特定する優れた方法は、StrictMode を使用することです。
- Android Vitals やその他のレポート サービスの履歴を分析し、エラーが最も多く発生しているゲームのリリース バージョンを確認します。バージョン管理履歴でソースコードを確認し、リリース間のコード変更を比較します。不審な点が見つかった場合は、変更または修正候補を 1 つずつ試してください。
- 最も多くの ANR を受け取っているデバイスと Android バージョンの Google Play ANR レポートの履歴を確認します。デバイスやバージョンが古い場合は、ゲームの収益性に影響しない限り、無視しても問題ない可能性があります。特定のユーザー グループがゲームをプレイできなくなるため、データを慎重に検討してください。詳細については、分布ダッシュボードをご覧ください。
- ゲームのソースコードを確認して、問題を引き起こす可能性のあるコード(finish など。正しく使用しないと破壊的になる可能性があります)を呼び出していないことを確認します。Android 開発について詳しくは、Android デベロッパー ガイドをご覧ください。
- データをレビューしてゲームビルドを Android Studio にエクスポートすると、C と C++ のコードを扱うことになるため、Android Memory Profiler、Android CPU Profiler、perfetto など、Unity の標準ソリューション以外のツールを最大限に活用できます。
Unity エンジンコード
Unity エンジン側で ANR が発生しているかどうかを確認するには、スタック トレースで libUnity.so
または libMain.so
を探します。見つかった場合は、次の手順を行います。
- まず、コミュニティ チャネル(Unity Forums、Unity Discussions、Stackoverflow)を検索します。
- 何も見つからない場合は、問題を解決するためにバグを報告してください。シンボリック化されたスタック トレースを提供して、エンジンのエンジニアがエラーをよりよく理解して解決できるようにします。
- 最新の Unity LTS で、問題に関連する改善が行われているかどうかを確認します。その場合は、そのバージョンを使用するようにゲームをアップグレードしてください。(この解決策は、一部のデベロッパーのみが利用できる場合があります)。
- コードでデフォルトではなくカスタムの
Activity
を使用している場合は、Java コードを確認して、アクティビティが問題を引き起こしていないことを確認します。
サードパーティの SDK
- すべてのサードパーティ ライブラリが最新の状態であり、最新バージョンの Android でクラッシュや ANR のレポートがないことを確認します。
- Unity フォーラムにアクセスして、エラーが後のバージョンで解決済みかどうか、または Unity やコミュニティ メンバーから回避策が提供されているかどうかを確認します。
- Google Play の ANR レポートを確認し、エラーが Google によってすでに特定されていないことを確認します。Google は一部の ANR を認識しており、積極的に修正に取り組んでいます。
システム ライブラリ
システム ライブラリは通常、デベロッパーの制御から遠く離れていますが、ANR の大きな割合を占めることはありません。ライブラリのデベロッパーに連絡したり、ログを追加して問題を絞り込んだりする以外に、システム ライブラリの ANR を解決するのは困難です。
終了理由
ApplicationExitInfo
は、ANR の原因を把握するための Android API です。ゲームで Unity 6 以降を使用している場合は、ApplicationExitInfo
を直接呼び出すことができます。古い Unity バージョンでは、Unity から ApplicationExitInfo
呼び出しを有効にするために、独自のプラグインを実装する必要があります。
Crashlytics も ApplicationExitInfo
を使用しますが、独自の実装ではよりきめ細かい制御が可能になり、より関連性の高い情報を含めることができます。