偵錯 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. 尋找 Build ID
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95

檢查遊戲程式碼

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

C++ 檔案名稱會遵循 Unity 專案中定義的組合名稱。否則,檔案名稱會採用預設的 Assembly-C# 名稱。舉例來說,圖 3 顯示檔案 Game.cpp 的錯誤 (以藍色醒目顯示),這是組合定義檔案中定義的名稱。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 回報記錄,瞭解哪些裝置和 Android 版本出現最多 ANR 問題。如果裝置或版本過時,只要不會影響遊戲的獲利能力,您通常可以放心忽略這些裝置或版本。請仔細研究資料,因為特定使用者群組將無法再玩遊戲。詳情請參閱「發布資訊主頁」。
  • 檢查遊戲原始碼,確保您不會呼叫任何可能造成問題的程式碼,例如,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;不過,您自己的實作方式可讓您更精細地控管,並納入更多相關資訊