把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 ...
随机推荐
- Nacos 1.2.1 集群搭建(三) Nginx 配置 集群
配置 Nginx 可以把.conf 文件拉到本地,配置好再传上去 #gzip on; upstream cluster{ server 192.168.0.113:8848; server 192.1 ...
- 【Vue】大总结
目录 vue大回顾 模板语法处理xss攻击 Vue单页面组件 ts泛型 sass\less\css的区别 ...toRef() defineEmits 练习 根据分数显示颜色 vue大回顾 1 前端发 ...
- BBS项目(五):xss攻击 上传图片问题 文章编辑、删除功能 用户头像修改 扩展部分
目录 添加文章功能完善 富文本编辑器上传图片问题 文章编辑功能 文章删除功能 用户头像修改 扩展部分 补充 项目总结 添加文章功能完善 下载第三方模块: pip install bs4 pip ins ...
- SCOI2005 互不侵犯 (状态压缩入门题)
使用状态压缩,最好了解 位运算使用 SCOI2005 互不侵犯 在 \(N\times N\) 的棋盘里面放 \(K\) 个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左 ...
- Codeforces #698 Div.2 (A~D题)个人题解记录
1478A. Nezzar and Colorful Balls 看半天题,然后才发现是统计最大值. int _; int main() { ios_base::sync_with_stdio(fal ...
- CompletableFuture 测试类
package com.example.apidemo.completableFutrue; import java.util.Random; import java.util.concurrent. ...
- vue axiox网络请求
一.首先安装axios ,vue-axios 前提:搭建一个vue3的项目 项目搭建参考:https://www.cnblogs.com/yclh/p/15356171.html 使用npm安装axi ...
- JUC包常用类原理
放眼望去,java.util.concurrent包下类大致包括:atomic 原子类.锁.并发集合.线程池.工具类.我们挑重要的了解一下. Atomic 原子类 Java针对并发编程已经有了各种锁, ...
- RL 的探索策略 | Exploration for RL
最近在草率地调研 RL 的 exploration. 这篇文章也比较草率,仅能起到辅助作用,不能代替读 review 或更精细的读 paper. 目录 0 总结写在最前面 1 主要参考资料 2 RL ...
- Idea 进行远程服务器debug操作
本文为博主原创,转载请注明出处: 很多时候为了定位服务器的问题,不方便定位时,采用idea 远程debug 服务器环境的服务进行问题定位,主要操作步骤如下: 1. 修改服务器服务的JVM 配置,开启远 ...