把Unity的日志保存到文件中
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的日志保存到文件中的更多相关文章
- logstash自己的日志保存到文件中:log4j2.properties
status = error dest = err name = PropertiesConfig property.filename = /gwlog/data/logstash/logs appe ...
- 【代码笔记】iOS-将log日志保存到文件
代码: #import "AppDelegate.h" #import "RootViewController.h" @implementation AppDe ...
- iOS - NSLog、UncaughtException日志保存到文件
转:http://blog.csdn.net/marujunyy/article/details/12005767 对于真机,日志没法保存,不好分析问题.所以有必要将日志保存到应用的Docunment ...
- C# log4net 配置及使用详解--日志保存到文件和Access(转)
按语: 最近项目要求选用Access数据库,但日志管理采用log4net,但保存到数据库一直没有成功,后按照如下配置在程序退出时可以成功保存. 开始新建文件应用log4net.dll ,重新编译就报 ...
- Object 保存到文件中
6月4日 Object 保存到文件中 Q. 你添加一个新类到你的项目当中且你希望可以保存这个类的一个实例对象到磁盘文件 并在需要时从磁盘文件读回到内存中 A. 方案 确保你的类遵循 NSCodi ...
- Unity在Android和iOS中如何调用Native API
本文主要是对unity中如何在Android和iOS中调用Native API进行介绍. 首先unity支持在C#中调用C++ dll,这样可以在Android和iOS中提供C++接口在unity中调 ...
- php cUrl模拟登录,cookie保存到文件中
源码如下: <?php header("Content-Type:text/html;charset=utf-8"); //模拟群友通讯录手机号登录 $curl = curl ...
- Python3操作MySQL,查询数据并保存到文件中
我们在测试过程中,可能需要到数据库中拉去一些数据,为从测试准备.比如最近在做接口性能测试的时候,就需要很多数据来支撑,所以就需要的数据库去查询数据,下面就是python3 查询 mysql 并且保存到 ...
- Unity脚本在层级面板中的执行顺序测试3
断断续续的写了3篇,以后有时间可以做成一个系列了 前面2篇测试了GameObject的顺序,以及Awake和OnEnable的时机: Unity脚本在层级面板中的执行顺序测试1 http://www. ...
- Unity脚本在层级面板中的执行顺序测试4-附加整理
测试4为一些附加内容,后续的各种tips都加在此. 前几篇测试的链接: Unity脚本在层级面板中的执行顺序测试1 http://www.cnblogs.com/hont/p/4298110.html ...
随机推荐
- Jenkins Pipeline 多分支流水线 Input length = 1
Jenkins 多分支流水线 构建过程中报错. [Pipeline] // node [Pipeline] End of Pipeline java.nio.charset.MalformedInpu ...
- 使用formdata在vue和django之间传递文件
在前端页面中如果有文件或者图片需要上传的场景下,通用做法是使用formdata将文件从前端传输到后台,在后台上传文件并将url保存在数据库. 当前项目是使用vue + Element UI + dja ...
- c#-微软2
练习-编写第一个代码: 在第一次练习中你将使用c#将神圣的程序员用语打印到控制台的标准输出 编写第一行代码: 在软件开发者中,有这么一个传统,那就是将"Hello World!"这 ...
- SSL 证书变革之时已至,这些变化你都清楚吗?
现代社会最离不开的是"安全",无论是生命.财产.数据还是其他任何事物都需要各种手段来保证安全,互联网自然也无法免俗.HTTP 协议作为无法加密数据,让所有通信数据都在网络中明文&q ...
- dmesg 时间误差现象
案例现象 这天收到监控平台发来的告警,说有台机器程序崩溃了 因为以前也有过相关的错误,根据经验,用 dmesg命令看下内核信息 发现有点不对劲,报错信息的时间跟告警时间不一致,正常来讲报错时间应该跟告 ...
- 0x62 图论-最小生成树
A题:走廊泼水节 链接:https://ac.nowcoder.com/acm/contest/1056/A 题目描述 给定一棵N个节点的树,要求增加若干条边,把这棵树扩充为完全图,并满足图的唯一最小 ...
- AtCoder Beginner Contest 179 个人题解(C欧拉筛,D前缀和,E循环节,F线段树)
补题链接:Here A - Plural Form 字符串,末尾有 s 的加es,不然加 s . B - Go to Jail 输入的时候判断一下是否连续相等即可 C - A x B + C (mat ...
- Codeforces Round #697 (Div. 3) A - G个人题解记录
Codeforces Round #697 (Div. 3) 1475A. Odd Divisor 问一个数是否有奇除数. 对 2 不断除,如果最后 n == 1即不可能存在,否在存在. int ma ...
- 什么是全同态加密(FHE)中的自举(Bootstrapping)?
PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全.密码学.联邦学习.同态加密等隐私计算领域的技术和内容. 全同态加密(Fully Homomorphic Encrypti ...
- spring--FactoryBean和BeanFactory有关系吗
BeanFactory 和 FactoryBean 是 Spring 框架中的两个不同的概念,两者是雷锋和雷峰塔的关系,就是没有任何关系,它们在 Spring 的依赖注入和 bean 创建过程中扮演不 ...