解決 Unity 遊戲中的 ANR 問題需要系統化流程:
整合報表服務
Android Vitals、Firebase Crashlytics 和 Backtrace (已認證的 Unity 合作夥伴) 等報表服務,可為您的遊戲提供大量的錯誤記錄和分析資料。在開發週期初期,將報表服務 SDK 整合至遊戲。分析哪項報表服務最符合您的遊戲需求和預算。
不同的回報服務擷取 ANR 的方式不同。加入第二個報表服務,提高取得有效資料的機會,以便您決定如何修正 ANR。
整合報表 SDK 不會影響遊戲效能或 APK 大小。
分析符號
請分析報表服務提供的報表,並確認堆疊追蹤是否以人類可讀的格式呈現。詳情請參閱「將 Unity 遊戲的 Android 當機和 ANR 問題符號化」。
如何檢查符號版本 ID
如果報表系統顯示缺少版本 ID,但版本機器儲存空間中仍有版本符號,則可以檢查符號的版本 ID,然後將符號上傳至報表服務。否則,您必須建立新版本才能上傳符號檔案。
在 Windows 或 macOS 上:
- 根據指令碼後端前往符號資料夾 (請參閱解決方法:)
- 使用下列指令 (在 Windows 上,請使用 Cygwin 執行
readelf
公用程式) - 您可以選擇使用 Grep 篩選文字輸出內容
- 尋找 Build ID
- 使用下列指令 (在 Windows 上,請使用 Cygwin 執行
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 轉換器產生的全名 (以橘色標示)。
如要檢查遊戲程式碼,請按照下列步驟操作:
- 檢查 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.so
或 libMain.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
;不過,您自己的實作方式可讓您更精細地控管,並納入更多相關資訊。