在Unity开发中,经常会用到一些报错上传的插件,比如Bugly。但是在使用过程中发现一个小问题:在上报的信息中只有插件设定好的信息,但是很多对排查错误很有用的信息却不能上报或者看不到。例如,我们需要知道此时的玩家状态,是在战斗中还是在别的状态;当前打开的面板是什么?当前游戏正处在一个什么样的流程中?
很明显,上述所提到的很多信息都是各个项目特有的。所以如何才能把这些信息添加进Bugly来上传呢?
1、原理
通过阅读Bugly插件的代码,不难找到上报日志的地方:
BuglyAgent._reportException(bool uncaught, string name, string reason, string stackTrace)
这个几个参数对应的意义如下:
uncaught表示是否在报错时强制退出游戏,这里可以先不用管。
我考虑通过修改name和stackTrace的值来达到我自定义上报内容的目的。比如在name前增加一些文本,表示当前的游戏状态啊(战斗中、加载中、战斗外);以及在stackTrace之后加上一些内容,展示当前的信息,比如打开了什么面板啊,选择的什么角色啊,等等其他愿意上传的信息。
所以我需要测试一下是否可行:
在这个函数如下位置加上自己的代码:
private static void _reportException (bool uncaught, string name, string reason, string stackTrace)
{
……
//add
trimFrameBuilder.Append ("测试1");
trimFrameBuilder.AppendLine ();
//end add
stackTrace = trimFrameBuilder.ToString ();
……
//add
name+="测试测试测试!";
//end add
PrintLog (LogSeverity.LogError, "ReportException: {0} {1}\n*********\n{2}\n*********", name, reason, stackTrace);
_uncaughtAutoReportOnce = uncaught && _autoQuitApplicationAfterReport;
ReportException (uncaught ? EXCEPTION_TYPE_UNCAUGHT : EXCEPTION_TYPE_CAUGHT, name, reason, stackTrace, uncaught && _autoQuitApplicationAfterReport);
}
这样打包测试一下,随便写个报错。然后打开Bugly:
妙啊!这样就完成目的了,这个方案测试可行。
PS:貌似在name里加换行符木有效果,不知道是为啥。
2、自定义报错内容
值得注意的是,这个BuglyAgent的脚本是在Plugins里面的,所以他是没法调用我们游戏中的脚本的,但是我们游戏中的脚本却可以调用BuglyAgent。
具体实现的思路其实很简单,就是通过委托来给Bugly传值就可以了:
using System;
using System.Collections.Generic;
///
/// Bugly的打印配置;
///
public class BuglyLogConfig
{
public static E_BuglyLogTag AppTag = E_BuglyLogTag.NULL;
///
/// 当前需要上报的标签;
///
public static string GetAppTag
{
get
{
if (AppTag == E_BuglyLogTag.NULL)
{
return null;
}
return $"【{AppTag.ToString()}】";
}
}
static List _LogAfterStackTrace = new List(8);
///
/// 在调用堆栈之后打印的部分;
///
public static List LogAfterStackTrace
{
get
{
_LogAfterStackTrace.Clear();
var list = GetTagList(AppTag);
int length = list.Count;
//添加各个自定信息;
for (int i = 0; i < length; i++)
{
_LogAfterStackTrace.Add(list[i].ToString());
}
//新增报错信息
return _LogAfterStackTrace;
}
}
///
/// 所有的需要额外打印的部分;
///
static Dictionary> DicAllListLogItem = new Dictionary>(8);
///
/// 增加一条打印内容;
///
/// 对应的标签
/// 名字
/// 取值方法
public static void AddLogItem(E_BuglyLogTag aTag, string name, Func getValFunc)
{
List mList = GetTagList(aTag);
int length = mList.Count;
for (int i = 0; i < length; i++)
{
var item = mList[i];
//如果已经有这个打印了,就刷新一下取值方法即可;
if (item.Name == name)
item.GetValueFunction = getValFunc;
return;
}
//此时需要新增;
BuglyLogItem newItem = new BuglyLogItem(aTag, name, getValFunc);
mList.Add(newItem);
}
///
/// 通过当前标签获得列表;
///
static List GetTagList(E_BuglyLogTag aTag)
{
List mList;
if (DicAllListLogItem.TryGetValue(aTag, out mList))
{
return mList;
}
//新增当前列表;
mList = new List(8);
DicAllListLogItem.Add(aTag, mList);
return mList;
}
class BuglyLogItem
{
///
/// 类型;
///
public E_BuglyLogTag Tag;
///
/// 取值方法;
///
public Func GetValueFunction;
///
/// 名字;
///
public string Name;
///
/// 设定打印内容;
///
///
///
///
public BuglyLogItem(E_BuglyLogTag tag, string name, Func method)
{
Tag = tag;
Name = name;
GetValueFunction = method;
}
public override string ToString()
{
return $"{Name} : {GetValueFunction?.Invoke()}";
}
}
}
///
/// Bugly上报时的标签;
///
public enum E_BuglyLogTag
{
NULL=0,
///
/// 登录界面
///
LOGIN=1,
///
/// 登录加载至主界面
///
LOGIN_TO_MAIN=2,
///
/// 主界面状态
///
MAIN=3,
///
/// 主界面进战斗
///
MAIN_TO_BATTLE=4,
///
/// 战斗中
///
BATTLE=5,
///
/// 战斗返回主界面
///
BATTLE_TO_MAIN=6,
}
之后在自己工程里写好代理和配置就OK了。
其实我觉得应该有现成的方法的,比如BuglyInit.MyLogCallbackExtrasHandler里面明明配置了很多信息,可惜就是不知道在哪里能看到。
希望大家写的程序都没有Bug~~