当游戏在手机/模拟器上卡死,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中检测死循环和卡死的更多相关文章

  1. Unity中Mesh分解与边缘高亮加上深度检测

    一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMe ...

  2. Unity中巧用协程和游戏对象的生命周期处理游戏重启的问题

    主要用到协程(Coroutines)和游戏对象的生命周期(GameObject Lifecycle)基础知识,巧妙解决了游戏重启的问题. 关于协程,这里有篇文章我觉得写的非常好,理解起来也很容易.推荐 ...

  3. Unity中的协程(一)

    这篇文章很不错的问题,推荐阅读英文原版: Introduction to Coroutines Scripting with Coroutines   这篇文章转自:http://blog.csdn. ...

  4. unity中Debug输出控制

    1 需求: (1)选择在界面.console中输出,并且能够设置保存到文档 (2)控制debug是否输出,可以在debug模式下输出,release模式下不输出 2 参考: 谢谢雨松同学的博客:htt ...

  5. 【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则

    作者:Williammao, 腾讯移动客户端开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/290.h ...

  6. 新装 Win7 系统装完驱动精灵,一打开到检测界面就卡死——原因与解决方案

    1.现象: 重装系统后,鼠标反应慢,且不能上网.因此装了个驱动精灵,准备更新下驱动,但驱动精灵一打开到检测界面就卡死(换驱动人生.鲁大师也一样). 2.原因: Win7 系统 iso 中自带的驱动程序 ...

  7. Unity中的GC以及优化

    [简介] 常见的 Unity GC 知识点总结出来的思维导图 Unity 官方文档,正巧在博客园发现了已经有位大神(zblade)把原文翻译出来了,而且质量很高~,译文地址 在这里.下面我就可耻地把译 ...

  8. Unity中的定时器与延时器

    JavaScript中的定时器与延时器,分别是 setInterval.setTimeout,对应的清理函数是:clearInterval.clearTimeout. 而在Unity中,则分别是:In ...

  9. Unity中UGUI之Canvas属性解读版本二

    Canvas Render Modes(渲染模式) 1.在screen空间中渲染2.在world空间中渲染 Screen Space-Overlay 在这个渲染模式中,UI元素将在场景的上面.如果场景 ...

随机推荐

  1. 图解 JVM 核心知识点(面试版)

    一.基本概念 1.1 OpenJDK 自 1996 年 JDK 1.0 发布以来,Sun 公司在大版本上发行了 JDK 1.1.JDK 1.2.JDK 1.3.JDK 1.4.JDK 5,JDK 6 ...

  2. 一本通 高手训练 1788 爬山 dp 斜率 凸包

    LINK:爬山 很早以前看的题目 发现自己想的完全不对 这道题还是比较有价值的. 先不考虑走的路线问题 考虑某个点能看到的最高的山. 分左边和右边来考虑 考虑左边 利用单调栈存长度单调递减的山 不能直 ...

  3. day7.关于字符串的相关操作

    一.字符串的相关操作 """ (1)字符串的拼接 (2)字符串的重复 (3)字符串跨行拼接 (4)字符串的索引 (5)字符串的切片: 语法 => 字符串[::] 完 ...

  4. Qt 乱码

    个人认识: 乱码的原因: 在编写代码时-->文件的格式--->编译器对文件进行编译的时候看到的只是二进制(乱码就出现在这里) 应合适方法 通知编译器(为什么说通知编译器呢?因为个人觉得这样 ...

  5. 【oracle】-集合运算:UNION,UNION ALL...

    在Oracle中提供了三种类型的集合操作: 并(UNION).交(INTERSECT).差(MINUS) UNION:求并,重复记录只显示一次. UNION ALL:求并集,显示所有记录信息. INT ...

  6. requests入门实践02_下载斗图拉最新表情包

    新版本移步:https://www.cnblogs.com/zy7y/p/13376228.html 下载斗图拉最新表情包 要爬取的目标所在网址:http://www.doutula.com/phot ...

  7. 023_go语言中的通道

    代码演示 package main import "fmt" func main() { messages := make(chan string) go func() { mes ...

  8. -bash: !": event not found

    在linux环境下执行一下代码时 printf "The first '%s,%s!' \n" Hello world 返回结果为“-bash: !”: event not fou ...

  9. 通过java程序(JSch)运行远程linux主机上的shell脚本

    如果您看完文章之后,觉得对您有帮助,请帮我点个赞,您的支持是我不竭的创作动力! 如果您看完文章之后,觉得对您有帮助,请帮我点个赞,您的支持是我不竭的创作动力! 如果您看完文章之后,觉得对您有帮助,请帮 ...

  10. C#/.Net集成RabbitMQ

    RabbitMQ简介 消息 (Message) 是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串. JSON 等,也可以很复杂,比如内嵌对象. 消息队列中间件 (Message Queu ...