偵錯 ANR

在 Unity 遊戲中解決 ANR 是一種系統性程序:

圖 1. 解決 Unity 遊戲 ANR 的步驟。

整合報表服務

報表服務 (例如 Android VitalsFirebase CrashlyticsBacktrace (經過認證的 Unity 合作夥伴) 可提供大規模的遊戲錯誤記錄和分析。在開發週期早期將報表服務 SDK 整合至遊戲中。請分析哪個報表服務最符合您的遊戲需求和預算。

不同的報表服務有不同的擷取 ANR 方法。請加入第二個報表服務,提高取得有效資料的機會,以做為修正 ANR 的決策。

整合報表 SDK 不會影響遊戲效能或 APK 大小。

分析符號

從報表服務分析報表,並檢查堆疊追蹤格式是否採用人類可讀的格式。詳情請參閱「將 Unity 遊戲的 Android 當機和 ANR 符號化」一文。

圖 2. Crashlytics 顯示版本 ID 缺少 libil2cpp.so 符號。

如何查看符號版本 ID

如果報表系統顯示缺少的建構 ID,但建構符號仍存在於建構機器儲存空間中,您可以檢查符號的版本 ID,然後將其上傳至報表服務。否則,必須建立新版本才能上傳符號檔案。

Windows 或 macOS:

  1. 根據指令碼後端前往符號資料夾 (請參閱「解析度」一節):
    1. 使用下列指令 (在 Windows 上,使用 Cygwin 執行 readelf 公用程式)
    2. 您可以選擇使用 Grep 指令來篩選文字輸出
    3. 尋找版本 ID
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

檢查遊戲程式碼

當堆疊追蹤在 libil2cpp.so 程式庫中顯示函式時,C# 程式碼就會發生錯誤,而程式碼已轉換為 C++libil2cpp.so 程式庫不僅包含遊戲程式碼,還具有外掛程式和套件。

C++ 檔案名稱會遵循 Unity 專案中定義的組合名稱。否則,檔案名稱會是預設的 Assembly-C# 名稱。例如,圖 3 顯示檔案 Game.cpp 的錯誤 (以藍色醒目顯示),也就是在 Assembly 定義檔案中定義的名稱。Logger 是 C# 指令碼中的類別名稱 (以紅色醒目顯示),後面接著函式名稱 (以綠色醒目顯示)。最後是 IL2CPP 轉換工具產生的全名 (以橘色醒目顯示)。

圖 3. 測試 Backtrace 中的專案呼叫堆疊。

請按照下列做法檢查遊戲程式碼:

  • 檢查 C# 專案是否有任何可疑的程式碼。C# 未處理的例外狀況通常不會導致 ANR 或應用程式當機。即便如此,也請確認程式碼在不同情況下都能正常運作。檢查程式碼是否使用第三方引擎模組,並分析最近的版本是否造成錯誤。此外,請檢查您是否最近更新過 Unity,或是否只在特定裝置上發生錯誤。
  • 將遊戲匯出為 Android Studio 專案。取得遊戲已轉換 C# 原始碼的完整存取權後,您就可以找出造成 ANR 的函式。C++ 程式碼看起來與 C# 程式碼大不相同,且程式碼轉換很少會發生問題。如果遇到任何問題,請向 Unity 提交支援單。
  • 查看遊戲原始碼,確認 OnApplicationFocus()OnApplicationPause() 回呼中執行的任何邏輯均已適當清理。
    • Unity 引擎設有暫停執行作業的逾時時間;這些回呼的工作負載過多可能會導致 ANR。
    • 在程式碼的各個部分新增記錄或導覽標記,可增強資料分析的效果。
  • 使用 Unity Profiler 調查遊戲效能。剖析應用程式也是協助找出可能造成 ANR 的瓶頸。
  • 如果要識別主執行緒上長時間的 I/O 作業,使用「嚴格模式」是不錯的選擇。
  • 分析 Android Vitals 或其他報表服務記錄,並查看發生錯誤的遊戲發布版本。請在版本管控記錄中查看原始碼,並比較不同版本之間的程式碼變更。如果發現可疑項目,請分別嘗試各項變更或可能的修正方法。
  • 檢查 Google Play ANR 回報記錄,找出收到最多 ANR 的裝置和 Android 版本。如果裝置或版本過舊,可以放心忽略這些版本 (如果這樣做不會影響遊戲的獲利能力)。由於特定群組的使用者無法再玩遊戲,因此請仔細研究相關資料。詳情請參閱發布資訊主頁
  • 檢查遊戲原始碼,確保您並未呼叫任何可能導致問題的程式碼。舉例來說,如果未正確使用 finish 就可能具有破壞性。如要進一步瞭解 Android 開發作業,請參閱 Android 開發人員指南
  • 查看資料並將遊戲版本匯出至 Android Studio 後,您須處理 C 和 C++ 程式碼,因此可以充分運用 Unity 標準解決方案以外的工具,例如 Android 記憶體分析器Android CPU 分析器perfetto

Unity 引擎程式碼

如要瞭解 Unity 引擎端是否發生 ANR,請在堆疊追蹤中查看 libUnity.solibMain.so。找到之後,請採取下列步驟:

  • 首先,請搜尋社群管道 (Unity 論壇Unity 討論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;不過,自己的實作能讓您更精細地控管及納入更相關的資訊