如何在Unity中检测死循环和卡死

 更新时间:2020年11月3日 15:19  
这篇文章主要介绍了在Unity中检测死循环和卡死的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

当游戏在手机/模拟器上卡死,logcat没有日志输出,也没有卡死堆栈信息或者bugly也没有捕获到异常,你是否很焦急?本文介绍一下我们项目中检测Unity卡死的方法,也许适合你使用。

实现原理

在绝大多数情况下我们可以认为Unity是单线程的,基于这点我们在Unity的系统函数FixedUpdate中统计游戏运行期间的总帧数,如果Unity没有卡死,那么TotalFrame是会一直累加的,如果在某一段时间内TotalFrame都不会变化了,则可以认为Unity已经卡死了

既然Unity的主线程已经卡死了,我们就需要用另一个线程用来定时检查unity主线程中的TotalFrame是否不会变化了

示例代码

using System;
using System.Threading;
using UnityEngine;

namespace KEngine
{
 /// <summary>
 /// 开另外一个线程检测unity是否被卡死
 /// </summary>
 public static class UnityThreadDetect
 {
  public static Thread _MainThread = System.Threading.Thread.CurrentThread;//获取unity线程
  private static int check_interval = 3000;//检测间隔

  public static void Start()
  {
   new Thread(CheckMainThread).Start();
  }
  
  static void CheckMainThread()
  {
   long frame = 0;
   while(!AppEngine.IsApplicationQuit)
   {
    frame = AppEngine.TotalFrame;
    Thread.Sleep(check_interval);
    if (frame == AppEngine.TotalFrame)
    {
     Log.LogToFile("unity thread dead,ThreadState:{0}",_MainThread.ThreadState);
     if (AppEngine.IsApplicationFocus)
     {
      //todo report error
     }
    }
   }
  }
 }
}

捕获卡死的方法名

在我们的游戏中一般出现卡死的情况都是在定时器里面,我们的定时器是通过在Unity的Update驱动定时器列表,当卡死时,在另一个线程中打印出定时器中正在执行的函数就可以定位到卡死的函数了。定时器可参考:UnityTimer中的Timer.cs

同时在Unity的Update进行派发多个事件,比如PreUpdate,Update,以便出问题更容易定位到卡在那儿

举例说明问题

下面举例我们遇到的出现卡死的问题

死循环

下面这个死循环在Unity中会卡死,而在.NET中不会,.NET中当i超过byte的最大值255时i会从0开始

public static void TesBadCode()
{
	byte i = 0; 
	while (true)
	{
		i++;
	}
}

目前我们遇到的绝大多数情况都是逻辑代码中写了where(true) do xxx 然后里面某些情况不会break,导致循环永远退不出来

屏蔽了事件系统

在某些系统中屏蔽掉了UGUI的事件系统,导致无法接受用户输入,这个问题不应该归类为Unity卡死,但用户反馈来看就是卡死了,无法操作。

重复添加定时器

起因是底层没有对同名定时器进行限制,在某些逻辑中误使用,出现每秒添加一个定时器,而定时器中的逻辑很大且长时间不退出的,当不断添加重复定时器就导致游戏运行越来越慢

重复注册事件

在一些界面的刷新函数和控制器函数,被频繁重复注册了事件,导致在抛出事件时,同一个函数被调用了N次,这个问题在Unity的Profiler中可以清晰看到函数的调用次数

扩展

递归调用

递归调用,会报stack overflow,不会让unity卡死

为什么无限循环递归调用不会卡死Unity?

这是因为每个方法的方法调用栈容量是有限的,当超出之后就会跳出报stack overflow,不会让应用程序卡死

public static void TesBadCode()
{
	while (true)
	{
		TesBadCode();
	}
}

总结

到此这篇关于在Unity中检测死循环和卡死的文章就介绍到这了,更多相关Unity检测死循环和卡死内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

相关文章

  • Unity实现桌面反弹的示例代码

    反弹球是小时候都玩过的网页小游戏,但是很多人都不知道怎样实现,本文就来介绍一下Unity实现桌面反弹的示例代码,感兴趣的可以了解一下...2021-05-30
  • hashMap扩容时应该注意这些死循环问题

    今天给大家带来的是关于Java的相关知识,文章围绕着hashMap扩容时的死循环问题展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下...2021-06-10
  • Unity UI实现拖拽旋转

    这篇文章主要为大家详细介绍了Unity UI实现拖拽旋转,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-06-06
  • 详解Unity 实现语音识别功能

    语言识别功能已经在我们身边普遍流行起来,在unity开发中语音识别也非常火热,今天就介绍下Unity自带的语音识别功能的实现,感兴趣的朋友跟随小编一起看看吧...2021-05-29
  • Unity 从UI中拖拽对象放置并拖动效果 附demo

    最近新接了个需求,要求模拟场景并生成3D对象,对象可以跟随鼠标移动效果,今天小编把我实现的demo分享到脚本之家平台,对Unity UI拖拽相关知识感兴趣的朋友跟随小编一起学习吧...2021-05-29
  • Unity连接MySQL并读取表格数据的实现代码

    本文给大家介绍Unity连接MySQL并读取表格数据的实现代码,实例化的同时调用MySqlConnection,传入参数,这里的传入参数个人认为是CMD里面的直接输入了,string格式直接类似手敲到cmd里面,完整代码参考下本文...2021-06-20
  • 新手必看Unity2019 2020保姆级安装教程

    这篇文章主要介绍了Unity2019 2020安装教程,本文分步骤通过图文并茂的形式给大家介绍Unity2019 2020安装方法,需要的朋友可以参考下...2021-05-29
  • 浅谈Unity中的Shader

    Shader,中文名为着色器,对很多开发者来说它是一个神秘的存在。Shader其实就是专门用来渲染图形的一种技术,通过shader,我们可以自定义显卡渲染画面的算法,使画面达到我们想要的效果...2021-06-26
  • Unity实现切割图集工具

    这篇文章主要为大家详细介绍了Unity实现切割图集工具,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-06-06
  • 聊聊Unity 自定义日志保存的问题

    这篇文章主要介绍了Unity 自定义日志保存的问题,之前unity5.x在代码中写了debug.log打包之后在当前程序文件夹下会有个对应的"outlog.txt",后来进行了更改,今天通过代码给大家介绍了Unity日志保存的问题,需要的朋友一起看看吧...2021-05-13
  • redis使用不当导致应用卡死bug的过程解析

    本文主要记一次找因redis使用不当导致应用卡死bug的过程,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧...2021-07-02
  • Unity打开淘宝app并跳转到商品页面功能的实现方法

    这篇文章主要给大家介绍了关于如何利用Unity打开淘宝app并跳转到商品页面功能的相关资料,这个功能目前在网上找不到相关的解决方法,所以自己写了出来,需要的朋友可以参考下...2021-07-07