偵錯 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 專案中定義的組件名稱。 否則檔案名稱會採用預設的 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 分析器調查遊戲效能。剖析應用程式也是找出可能導致 ANR 瓶頸的好方法。
  • 如要找出主執行緒上耗時的 I/O 作業,建議使用嚴格模式
  • 分析 Android Vitals 或其他報表服務的記錄,並檢查錯誤發生次數最多的遊戲發布版本。在版本控制記錄中查看原始碼,並比較不同版本之間的程式碼變更。如果發現可疑之處,請逐一嘗試各項變更或可能的修正方式。
  • 查看裝置和 Android 版本在 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 是 Android API,可協助您瞭解 ANR 發生原因。如果您的遊戲使用 Unity 6 以上版本,可以直接呼叫 ApplicationExitInfo。如果是舊版 Unity,您必須自行實作外掛程式,才能從 Unity 啟用 ApplicationExitInfo 呼叫。

Crashlytics 也會使用 ApplicationExitInfo,但您自行導入可提供更精細的控制權,並納入更多相關資訊