当前位置:首页|资讯

Unity中ANR问题汇总及处理办法

作者:Metaverse大衍神君发布时间:2024-10-13

ANR是Application Not Responding的首字母缩写,意思是应用无响应。Android系统下应用程序如果超过一定时间无法获得系统回调响应就会发生ANR。

ANR发生时表现

那么Unity在Android平台下发生ANR的情况有哪些?我们该如何着手处理呢?

1. 第一种情况

           “main” tid=1 Time Waiting

           jdk.internal.misc.Unsafe.park(Native method) 

           android.app.Activity.performPause

           当UnityPlayerActivity接收到一个OnPause()的回调时,UnityPlayerActivity会通知引擎它被暂停,这时引擎会调用每个脚本的OnApplicationPause的事件回调方法,同时引擎会停止所有Component组件和引擎模块,例如声音播放、渲染、游戏循环、动画等。为了让引擎有时间处理这些事务,Unity Android Player会等待4秒来等待引擎,如果这个同步时间超过5秒就会触发ANR。这种情况我们可以从功能模块性能优化,避免GameObject层级过深,提出不需要逻辑模块方便去着手。

2. 第二种情况

            com.unity3d.player.UnityPlayer.updateDisplayInternal

            在UnityPlayer类种的updateDisplayInternal方法创建了一个初始基数为0的信号量(Semaphore)用来实现与引擎同步。同时该方法中还会创建一个Runnable,用来负责重新创建图形状态的Native方法,调用Semaphore.release将使许可计数增加1次, 确保当前帧不再使用主窗口,该方法进入等待状态,尝试使用semaphore.tryAcquire从信号量获取许可。如果GPU出于某种原因将信号量持有了4秒,而操作的另一部分需要额外的一秒,这就可能会导致ANR。GPU上发生这种情况的根本原因不清楚,但一般是由于GPU负载过高或GPU驱动会导致此类问题,我们可以从降低GPU过载和做好高低机型图形功能适配去着手。

3. 第三种情况

            com.unity3d.player.UnityPlayer.nativeUnitySendMessage

            这个问题一般发生在引用程序恢复(OnResume)时,会发送多条消息。因为所有消息在游戏在后台时会做了排队处理,并会在恢复时同步发出。由于引擎有自身的工作负载,同时加上开发者创建的自己工作负载的第三方代码,可能会使设备的资源过载,特别是主线程。主线程运行应用程序的用户界面通常是ANR的主要位置。因此住线程上任何增加工作负载的情况都会增加ANR的可能性。这种情况我们可以减轻主线程的工作负载,避免UnitySendMessage调用频率过高,对重复相同的消息进行屏蔽或过滤。

4. 第四种情况

            Android.os.BinderProxy.transactNative

            Binder是与Android进行间的通信机制;它与内部线程共同工作,主要由于binder调用慢所以也会导致ANR。这种情况一般很少由于Unity引擎本身问题,多与第三方库有关。一般情况下我们可以从屏蔽一些第三方库和SDK入手。

5. 第五种情况

            android.os.MessageQueue.nativePollOnce

            发生这种情况只是无法响应线程的指示器,它不是发生ANR的根本原因,它只是线程间出现了问题的一个延迟指示。这种情况我们我们应从线程间消息阻塞逻辑去着手。


6. 其他容易发上ANR的情况

            包括长时间运行、Low Memory、低端设备、游戏内广告(视频居多),这些情况基本上也都是上述问题包含的。总结下来一般ANR情况都是由耗时操作、Android原生界面卡顿、线程资源竞争和内存泄漏或复写引起的。那更通用处理方式可以尝试优化代码逻辑、耗时操作的异步处理、增加ANR超时响应回调处理或采用一些检测分析工具来辅助处理。

针对ANR的处理,Unity引擎上也做了一些工作,比如:

  1. 改进了ANR后的恢复的逻辑

  2. 优化引擎内部的timeout的逻辑

  3. 让用户自定义控制timeout时间,比如不再是5s

  4. 将符号信息直接内嵌到AAB包中,方便出现ANR时快速方便恢复堆栈查找问题。

  5. 增加了GameActivity来针对游戏项目入口点,可以更好的支持lifecycle与输入事件的线程,通知支持在引擎外更新GameActivity包。

  6. 在C#层通过AndroidJavaClass与Native层交互,避免使用UnitySendMessage导致频率过高引擎的消息阻塞

  7. 在Unity C#层增加了应用程序退出时信息的查询接口,可以在应用程序退出时手机崩溃、ANR等信息。

不过这些功能是在不同版本的Unity上添加的,最后这里提供一张图来帮助大家理解Unity针对ANR做的功能改进对应的Untiy版本。

Unity针对ANR做的功能改进对应的Untiy版本



Copyright © 2024 aigcdaily.cn  北京智识时代科技有限公司  版权所有  京ICP备2023006237号-1