偵錯 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;不過,您自己的實作方式可讓您更精細地控管,並納入更多相關資訊