Unity的日志事件

Unity提供了两个日志回调API,这两个回调函数的参数都是一样的,通过这个API可以在真机上把Debug.Log/LogWarning/LogError 日志输出到文件中保存,我建议使用Application.logMessageReceivedThreaded

Application.logMessageReceivedThreaded
Application.logMessageReceived OnLogCallback(string condition, string stackTrace, LogType type) //回调函数

Application.logMessageReceived

此事件仅在主线程上触发。如果你的处理程序需要访问限制到主线线程的Unity API的一部分,或者由于其他原因你的处理程序不是线程安全的,就使用它

Application.logMessageReceivedThreaded

无论消息是否在主线程上传入,此事件都将被触发。这意味着处理程序代码必须是线程安全的。它可以从不同的线程调用,也可以并行调用。确保仅从允许从主线程以外的线程调用的处理程序中访问Unity API

注意:不必同时订阅两个应用消息:logMessageReceived和 Application.logMessageReceivedThreaded。对于主线程上的消息,也将调用多线程变体。

看到QFramework中提到这一样一句话:

如果只是使用 Application.logMessageReceived 的时候,在真机上如果发生 Error 或者 Exception 时,收不到堆栈信息。但是使用了 Application.logMessageReceivedThreaded 就可以接收到堆栈信息了,不过在处理 Log 信息的时候要保证线程安全。

因为写入日志的实现方式我和他是不一样的,我是在主线程中写入日志的,而他是再开了一个线程来写入日志。所以我是没有遇到他这个问题。

参数解释

OnLogCallback(string condition, string stackTrace, LogType type)

condition:就是代码中主动打印的日志

stackTrace:堆栈信息。如果Project Setting中设置的堆栈为ScriptOnly,则除了程序出错,其它的Log是不会有堆栈信息的,而如果使用:Environment.StackTrace来代替stackTrace,则会有一串很长很长的堆栈。

目前我们的项目在Project Setting中也是设置的Script Only

Exception也可捕捉到

在程序中抛出异常,在日志回调中也可以捕捉到,比如在断言中抛出异常

 public static void Assert(object obj, string msg, params object[] args)
{
if (obj==null)
{
string formatMsg = $"[Error]{DateTime.Now.ToString("HH:mm:ss.fff")} Assert Failed! {string.Format(msg, args)}";
throw new Exception(formatMsg);
}
}

查看stackTrace

我的测试环境如下:

unity2019.3.7 个人版 打包pc版

设置一:Project Settings中设置的StackTrace全部为ScriptOnly

设置二:Project Settings中设置的StackTrace全部为Full

打的是Mono包而非IL2Cpp,设置为.NET 4.x或 .NET Stand都尝试过,结果是一样。

堆栈设置为ScriptOnly

测试代码如下,在日志中不会打印调用堆栈,对于error也没有堆栈,只有真正的exception发生才会有出错堆栈

void OnClickBtn1()
{
Debug.Log("test log");
Debug.LogWarning("test log warn");
Debug.LogError("test log error");
//text1是不存在的,特意让程序出错,查看输出堆栈
text1.text = "text";
}

[2020-11-27 14:54:35][Log]test log

[2020-11-27 14:54:35][Warning]test log warn

[2020-11-27 14:54:35][Error]test log error

[2020-11-27 14:54:35][Exception]NullReferenceException: Object reference not set to an instance of an object

TestLogStackTrace.OnClickBtn2 () (at :0)

UnityEngine.Events.InvokableCall.Invoke () (at <73b499366e5241bda47e5da76897738b>:0)

UnityEngine.Events.UnityEvent.Invoke () (at <73b499366e5241bda47e5da76897738b>:0)

UnityEngine.UI.Button.Press () (at :0)

UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at :0)

UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at :0)

UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at :0)

UnityEngine.EventSystems.EventSystem:Update()

把堆栈打印出来

而在某些情况下,我们希望把函数的调用者打印出来,可以通过StackTrace

测试代码如下:

void OnClickBtn1()
{
Debug.Log(this.name + "click stacktrace:\n" + new StackTrace(true) + "\n");
}

输出结果如下:

[2020-11-27 17:43:45]Canvasclick stacktrace:

at TestLogStackTrace.OnClickBtn1 () [0x00000] in <3010e64894cc4fd9b62b8f33b1cc1f8a>:0

at UnityEngine.Events.InvokableCall.Invoke () [0x00000] in <73b499366e5241bda47e5da76897738b>:0

at UnityEngine.Events.UnityEvent.Invoke () [0x00000] in <73b499366e5241bda47e5da76897738b>:0

at UnityEngine.EventSystems.EventSystem.Update () [0x00000] in <3fe6533ed4534466954fc02559cdbfd7>:0

堆栈设置为Full

设置为Full之后,在日志文件中,对于Debug.Log ~ Debug.LogError都会有非常非常长的一串Unity的调用堆栈

[2020-11-27 14:58:47][Log]test  log
0x00007FFCA6DB060C (UnityPlayer)
0x00007FFCA6DB3933 (UnityPlayer)
0x00007FFCA6DA32CD (UnityPlayer)
0x00007FFCA7646A9E (UnityPlayer) UnityMain
0x00007FFCA71B9011 (UnityPlayer) UnityMain
0x000001C7AAEDF6EE (Mono JIT Code) (wrapper managed-to-native) UnityEngine.DebugLogHandler:Internal_Log (UnityEngine.LogType,UnityEngine.LogOption,string,UnityEngine.Object)
0x000001C7AAEDF3FB (Mono JIT Code) UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
0x000001C7AAEDF0D0 (Mono JIT Code) UnityEngine.Logger:Log (UnityEngine.LogType,object)
0x000001C7AAEDEE4A (Mono JIT Code) UnityEngine.Debug:Log (object)
0x000001C7AAF2F693 (Mono JIT Code) TestLogStackTrace:OnClickBtn2 ()
0x000001C7AAF2F649 (Mono JIT Code) UnityEngine.Events.InvokableCall:Invoke ()
0x000001C7AAF2F39B (Mono JIT Code) UnityEngine.Events.UnityEvent:Invoke ()
0x000001C7AAF2F123 (Mono JIT Code) UnityEngine.UI.Button:Press ()
0x000001C7AAF2F063 (Mono JIT Code) UnityEngine.UI.Button:OnPointerClick (UnityEngine.EventSystems.PointerEventData)
0x000001C7AAF2F009 (Mono JIT Code) UnityEngine.EventSystems.ExecuteEvents:Execute (UnityEngine.EventSystems.IPointerClickHandler,UnityEngine.EventSystems.BaseEventData)
0x000001C7AAF2A8F2 (Mono JIT Code) UnityEngine.EventSystems.ExecuteEvents:Execute<T_REF> (UnityEngine.GameObject,UnityEngine.EventSystems.BaseEventData,UnityEngine.EventSystems.ExecuteEvents/EventFunction`1<T_REF>)
0x000001C7AAF2ED0B (Mono JIT Code) UnityEngine.EventSystems.StandaloneInputModule:ReleaseMouse (UnityEngine.EventSystems.PointerEventData,UnityEngine.GameObject)
0x000001C7AAF25773 (Mono JIT Code) UnityEngine.EventSystems.StandaloneInputModule:ProcessMousePress (UnityEngine.EventSystems.PointerInputModule/MouseButtonEventData)
0x000001C7AAEFFD73 (Mono JIT Code) UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent (int)
0x000001C7AAF0FF8B (Mono JIT Code) UnityEngine.EventSystems.StandaloneInputModule:ProcessMouseEvent ()
0x000001C7AAF1FEA3 (Mono JIT Code) UnityEngine.EventSystems.StandaloneInputModule:Process ()
0x000001C7AAF04AFF (Mono JIT Code) UnityEngine.EventSystems.EventSystem:Update ()
0x000001C7677FAA20 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007FFCAF2FCBA0 (mono-2.0-bdwgc) mono_get_runtime_build_info
0x00007FFCAF282112 (mono-2.0-bdwgc) mono_perfcounters_init
0x00007FFCAF28B10F (mono-2.0-bdwgc) mono_runtime_invoke
0x00007FFCA71554DD (UnityPlayer) UnityMain
0x00007FFCA71528B3 (UnityPlayer) UnityMain
0x00007FFCA713BBD3 (UnityPlayer) UnityMain
0x00007FFCA713BC8D (UnityPlayer) UnityMain
0x00007FFCA6ED1D30 (UnityPlayer) UnityMain
0x00007FFCA701A717 (UnityPlayer) UnityMain
0x00007FFCA701A7B3 (UnityPlayer) UnityMain
0x00007FFCA701CBBB (UnityPlayer) UnityMain
0x00007FFCA6DD7E5E (UnityPlayer)
0x00007FFCA6DD6BBA (UnityPlayer)
0x00007FFCA6DDAA7C (UnityPlayer)
0x00007FFCA6DDE56B (UnityPlayer) UnityMain
0x00007FF6FC6211F2 (UGUIDemo)
0x00007FFD26047974 (KERNEL32) BaseThreadInitThunk
0x00007FFD2694A0B1 (ntdll) RtlUserThreadStart

测试结果文件

结果文件我上传在 我的github

把Unity的日志保存到文件中的更多相关文章

  1. logstash自己的日志保存到文件中:log4j2.properties

    status = error dest = err name = PropertiesConfig property.filename = /gwlog/data/logstash/logs appe ...

  2. 【代码笔记】iOS-将log日志保存到文件

    代码: #import "AppDelegate.h" #import "RootViewController.h" @implementation AppDe ...

  3. iOS - NSLog、UncaughtException日志保存到文件

    转:http://blog.csdn.net/marujunyy/article/details/12005767 对于真机,日志没法保存,不好分析问题.所以有必要将日志保存到应用的Docunment ...

  4. C# log4net 配置及使用详解--日志保存到文件和Access(转)

    按语: 最近项目要求选用Access数据库,但日志管理采用log4net,但保存到数据库一直没有成功,后按照如下配置在程序退出时可以成功保存. 开始新建文件应用log4net.dll  ,重新编译就报 ...

  5. Object 保存到文件中

    6月4日 Object 保存到文件中  Q. 你添加一个新类到你的项目当中且你希望可以保存这个类的一个实例对象到磁盘文件 并在需要时从磁盘文件读回到内存中  A. 方案  确保你的类遵循 NSCodi ...

  6. Unity在Android和iOS中如何调用Native API

    本文主要是对unity中如何在Android和iOS中调用Native API进行介绍. 首先unity支持在C#中调用C++ dll,这样可以在Android和iOS中提供C++接口在unity中调 ...

  7. php cUrl模拟登录,cookie保存到文件中

    源码如下: <?php header("Content-Type:text/html;charset=utf-8"); //模拟群友通讯录手机号登录 $curl = curl ...

  8. Python3操作MySQL,查询数据并保存到文件中

    我们在测试过程中,可能需要到数据库中拉去一些数据,为从测试准备.比如最近在做接口性能测试的时候,就需要很多数据来支撑,所以就需要的数据库去查询数据,下面就是python3 查询 mysql 并且保存到 ...

  9. Unity脚本在层级面板中的执行顺序测试3

    断断续续的写了3篇,以后有时间可以做成一个系列了 前面2篇测试了GameObject的顺序,以及Awake和OnEnable的时机: Unity脚本在层级面板中的执行顺序测试1 http://www. ...

  10. Unity脚本在层级面板中的执行顺序测试4-附加整理

    测试4为一些附加内容,后续的各种tips都加在此. 前几篇测试的链接: Unity脚本在层级面板中的执行顺序测试1 http://www.cnblogs.com/hont/p/4298110.html ...

随机推荐

  1. esp8266 水墨屏显示中文之大号字体

    想要显示更大的字体,操作流程如下: 一.下载ESP8266文字显示相关库 链接: https://pan.baidu.com/s/1q9m0K2_egAmiMmD5IBfQ4Q 提取码: wtr2 二 ...

  2. 彻底干掉了Windows的cmd,一个字:爽!

    彻底干掉了Windows的cmd,一个字:爽! 先说一句:Windows下的 cmd 就是垃圾! 习惯了Ubuntu和Mac的Terminal,再去用Windows的 cmd 简直难以忍受. 今天就向 ...

  3. ABAP RSA方式调用工行银企直联API

    目录 一.研究背景 二.   RSA简介 RSA是非对称加密的一种. 对称加密算法: 在加密和解密时使用的是同一个秘钥:如图所示: 非对称加密算法: 需要一对密钥来加密解密,这两个密钥是公开密钥(pu ...

  4. Windows10/11 wsl2 安装 ArchLinux 子系统

    这篇文章针对的是在win11系统的wsl2下安装ArchLinux系统,网上很多中文教程都是使用LxRunOffline去做的,但是实际上该方法已经过时了,目前有更加先进的ArchWSL方式. 如果用 ...

  5. 51 nod | 1007 正整数分组(背包DP)

    补题链接:Here 将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的. 输入 第1行:一个数N,N为正 ...

  6. CodeCraft-21 and Codeforces Round #711 (Div. 2) A~C 个人题解

    补题链接:Here 1498A. GCD Sum 题意:给定一个 gcdSum 操作:\(gcdSum(762) = gcd(762,7 + 6 + 2) = gcd(762,15) = 3\) 请问 ...

  7. Android内存泄露检测 LeakCanary2.0(Kotlin版)的实现原理

    本文介绍了开源Android内存泄漏监控工具LeakCanary2.0版本的实现原理,同时介绍了新版本新增的hprof文件解析模块的实现原理,包括hprof文件协议格式.部分实现源码等. 一.概述 L ...

  8. ios ipa包上传需要什么工具

    ​ 目录 ios ipa包上传需要什么工具 前言 一.IPA包的原理 二.IPA包上传的步骤 1.注册开发者账号 2.apk软件制作工具创建应用程序 3.构建应用程序 4.生成证书和配置文件 5.打包 ...

  9. P2895

    本题用时:01:44:20. 算法:BFS 期间固然去逛了逛淘宝买了两个东西,但毕竟还是太久了.我因为忘记判断是否出界而浪费了好多时间,后来才半天想起来,这便是用了这么长时间的原因. 之后提交代码只有 ...

  10. C#单向链表的实现

    节点 public class ListNode { public ListNode(int NewValue) { Value = NewValue; } //前一个 public ListNode ...