UnityDebugViewer是一个功能强大的Unity Log查看工具,它集成了Unity Console Window的所有功能,并在此基础上加入了搜索、查看堆栈源码和Log统计等功能。
通过使用UnityDebugViewer,无需安装Android Studio或者下载SDK就可以很方便地查看Unity在手机上输出的Log并获取相应的堆栈信息。此外,UnityDebugViewer还提供了解析Unity保存在手机上的Log文件的功能,帮助开发者使用UnityDebugViewer快速分析、定义游戏在手机上运行时遇到的问题。
支持版本
UnityDebugViewer使用Unity 5.6.6f2开发完成,能支持Unity 4.x以上版本
如何使用
方法一:
- 将本仓库克隆至本地
- 将
UnityDebugViewer文件夹移植至项目中Assets目录下的任意文件夹 - 选择
Window->Debug Viewer打开窗口
方法二:
- 下载最新版本的Package
- 将下载好的Package导入至项目中
- 选择
Window->Debug Viewer打开窗口
注意:如果想要使用
UnityDebugViewer提供的接口,需要避免将UnityDebugViewer存放至名称为Editor文件夹之下(包括子文件夹)
基本功能
- 工具栏功能:
-
清理log(Clear)、折叠log(Collapse)、运行时清理log(Clear On Player)、遇到error时暂停(Error Pause)和过滤log类型等
Console Window具备的功能; -
滚动至最新log:勾选
Auto Scroll按钮,当有新的log输出至窗口时,滚动条会自动滚动至底部; -
统计Log:勾选
Show Analysis按钮,窗口下方会展示出当前所有log的统计信息(可以通过切换Sort Type来改变当前用于筛选log的类型,也可以在右边的搜索框输入关键词或者正则表达式进行搜索);
-
筛选
log的功能- 启用正则表达式搜索:选中工具栏搜索框右侧的
Regex按钮,就可以输入正则表达式对log进行筛选; - 显示log的时间:勾选工具栏搜索框右侧的
Time按钮,将显示产生log的时间,此时可以对时间进行筛选,从而获取某个时间段内产生的所有log;
- 启用正则表达式搜索:选中工具栏搜索框右侧的
-
- 堆栈相关功能:
- 其他功能:
拓展功能
UnityDebugViewer默认提供了Editor、ADB Forward、ADB Logcat和Log File四种模式,它们分别拥有不同的拓展功能。
Editor
UnityDebugViewer的Editor模式等同于Unity自带的Console Window,它能获取使用UnityEngine.Debug输出的log以及项目编译、运行时产生的告警或者异常信息。

ADB Forward
UnityDebugViewer的ADB Forward模式集成了adb的forward指令,允许使用者通过Tcp将项目在手机上运行时产生的数据传输至UnityDebugViewer上并显示。

使用方式:
- 将
UnityDebugViewer/Test/TestTcp.cs附加到项目初始场景的某一空物体中- 在将项目构建成apk时勾选
Development,然后将构建好的apk安装至安卓设备并运行- 使用usb连接线将安卓设备连接至电脑,并开启
开发者调试选项- 根据需要修改
PC Port(PC端用于数据转发的端口)和Phone Port(手机端用于数据转发的端口)- 点击
Start开始收集并输出log,点击Stop停止收集log
通过使用UnityDebugViewer提供的工具类,使用者可以很方便地定义并传输自定义的数据,其基本步骤如下:
- 定义用于Tcp传输的数据结构
[Serializable] [StructLayoutAttribute(LayoutKind.Sequential, Pack=1)] struct TestStruct { public int c; /// 字符串,SizeConst为字符串的最大长度 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string str; /// int数组,SizeConst表示数组的个数 /// 初始化的数组长度必须和SizeConst一致,例test = new int[6]; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public int[] test; }
- 在手机端上创建Tcp Server并发送数据
- 创建一个UnityDebugViewerTransfer实例,并调用CreateServerSocket方法创建一个Tcp Server Socket
- 使用
UnityDebugViewerTransferUtility.StructToBytes将数据结构序列化成byte数组 - 调用UnityDebugViewerTransfer实例的SendData方法向已建立连接的Client发送数据
/// 创建一个tcp传输实例 var transfer = new UnityDebugViewerTransfer(); /// 创建一个tcp server socket并侦听50000端口 transfer.CreateServerSocket(50000); var testData = new TestStruct(); byte[] sendData = UnityDebugViewerTransferUtility.StructToBytes(testData); transfer.SendData(sendData);
- 检查adb以及设备连接状态,然后使用
adb forward指令开启ADB Forward进程,并建立转发端口
private void StartADBForward() { if (UnityDebugViewerWindowUtility.CheckADBStatus() == false) { return; } string adbPath = UnityDebugViewerWindowUtility.GetAdbPath(); startForwardProcess = UnityDebugViewerADBUtility.StartForwardProcess(pcPort, phonePort, adbPath); /// 成功创建adb forward进程 if (startForwardProcess) { ... } }
- 在Editor下创建Tcp Client并接收数据
- 创建一个UnityDebugViewerTransfer实例,并绑定receiveDaraFromServerEvent回调事件
- 调用UnityDebugViewerTransfer实例的ConnectToServer方法,创建一个Tcp Client并连接到指定的Server
- 在receiveDaraFromServerEvent回调事件中处理从服务器收到的数据
- 使用UnityDebugViewerTransferUtility.BytesToStruct将byte数组反序列化为数据结构
private void ReceiveDataFromServerHandler(byte[] data) { TestStruct logData = UnityDebugViewerTransferUtility.BytesToStruct<TestStruct>(data); ... } private void StartADBForward() { if (UnityDebugViewerWindowUtility.CheckADBStatus() == false) { return; } string adbPath = UnityDebugViewerWindowUtility.GetAdbPath(); startForwardProcess = UnityDebugViewerADBUtility.StartForwardProcess(pcPort, phonePort, adbPath); /// 成功创建adb forward进程 if (startForwardProcess) { UnityDebugViewerTransferUtility.receiveDaraFromServerEvent += ReceiveDataFromServerHandler; UnityDebugViewerTransferUtility.ConnectToServer("127.0.0.1", port); } }
- 停止ADB Forward进程,并调用UnityDebugViewerTransfer的Clear方法清理Tcp socket和侦听进程
private void StopADBForward() { string adbPath = UnityDebugViewerWindowUtility.GetAdbPath(); UnityDebugViewerADBUtility.StopForwardProcess(adbPath); startForwardProcess = false; /// will abort process, should excute at last UnityDebugViewerTransferUtility.Clear(); }
说明:
- UnityDebugViewerTransferUtility是一个在UnityDebugViewerTransfer基础上封装而成的工具类,它管理一个静态UnityDebugViewerTransfer实例,并提供了许多在使用UnityDebugViewerTransfer时会用到的公共接口
- UnityDebugViewerTransferUtility封装了UnityDebugViewerTransfer的所有公有属性和方法,在大部分情况下,可以直接将UnityDebugViewerTransferUtility当成UnityDebugViewerTransfer实例使用
- 但如果需要同时使用多个UnityDebugViewerTransfer实例,则需要自己创建UnityDebugViewerTransfer实例并进行管理
Assets/Test/TestTcp.cs提供了如何获取、转发log数据的例子,关于如何添加一个自定义模式用于展示自定义数据,详见添加自定义的模式。
using UnityEngine; namespace UnityDebugViewer { public class TestTcp : MonoBehaviour { private UnityDebugViewerTransfer transfer; private void Awake() { /// 创建一个tcp传输实例 transfer = new UnityDebugViewerTransfer(); /// 创建一个tcp server socket并侦听50000端口 transfer.CreateServerSocket(50000); /// 开始收集log信息 Application.logMessageReceivedThreaded += CaptureLogThread; DontDestroyOnLoad(this.gameObject); } private void OnDestroy() { Application.logMessageReceivedThreaded -= CaptureLogThread; transfer.Clear(); } private void CaptureLogThread(string info, string stacktrace, UnityEngine.LogType type) { if (transfer == null) { return; } lock (transfer) { /// 将收集到的log数据序列化成byte[] /// 并转发至连接到指定端口的tcp client socket var logData = new TransferLogData(info, stacktrace, type); byte[] sendData = UnityDebugViewerTransferUtility.StructToBytes(logData); transfer.SendData(sendData); } } } }
ADB Logcat
UnityDebugViewer的ADB Logcat模式集成了adb的logcat命令,无需安装Android Studio或者配置SDK环境,只需要使用usb线将手机连接至电脑,就可以直接看到项目在手机上运行时输出的所有log以及产生log的堆栈信息。

使用方式:
- 在已开启
开发者调试选项的安卓设备上运行项目- 使用usb连接线将安卓设备连接至电脑
- 修改
Tag Filter以指定使用logcat命令获取哪些log信息
Tag Filter为Unity表示只捕获Unity生成的logTag Filter为空表示捕获安卓系统产生的所有log- 点击
Start开始从手机上捕获log并输出至窗口,点击Stop停止捕获log;
Log File
UnityDebugViewer的Log File模式提供了解析log文件的功能,其能解析的log格式与UnityDebugViewer将log保存至文件时使用的格式一致,如下所示:
添加自定义模式
除了使用UnityDebugViewer提供的四种默认模式,UnityDebugViewer还允许使用者根据实际的需求添加自定义的模式。添加自定义模式的步骤并不复杂,如下所示:
- 在任一
Editor文件夹下创建一个继承自UnityDebugViewer.UnityDebugViewerIntermediaryEditor的类 - 使用
[InitializeOnLoadMethod]标记一个静态方法作为初始化入口 - 在初始化入口中使用
UnityDebugViewerEditorManager.RegisterMode方法注册自定义模式UnityDebugViewerEditorManager.RegisterMode<T>(string mode, int order)
T: UnityDebugViewerIntermediaryEditor或者其子类参数:
mode: 自定义模式的名称
order: 自定义模式的权重,用于决定其在下拉列表中的显示顺序。如果权重相同,则会根据注册的顺序来显示
- 覆写
UnityDebugViewer.UnityDebugViewerIntermediaryEditor提供的方法:Clear:点击工具栏的Clear按钮时被调用OnGUI:在绘制工具栏时被调用,可用于在工具栏上绘制自定义的UIStartCompiling:项目开始编译时被调用,可用于清理线程等数据
- 使用
UnityDebugViewerLogger.Log、UnityDebugViewerLogger.LogWarning或者UnityDebugViewerLogger.LogError方法将log输出至自定义模式对应的UnityDebugViewerEditor上
为了方便使用者快速掌握如何添加自定义的模式,UnityDebugViewer提供了UnityDebugViewer/Test/Editor/TestCustomMode.cs作为添加自定义模式的例子。以下是TestCustomMode.cs的内容和详细注释,它包括了添加自定义模式的所有步骤。

using UnityEngine; using UnityEditor; namespace UnityDebugViewer { public class TestCustomMode : UnityDebugViewerIntermediaryEditor { /// <summary> /// 模式的名称 /// </summary> private const string MODE_NAME = "TestCustomMode"; /// <summary> /// 标记初始化的入口 /// </summary> [InitializeOnLoadMethod] private static void InitializeTestCustomMode() { /// 自定义模式的权重,用于决定其在下拉列表中的显示顺序 int order = 10; /// 添加自定义的模式 UnityDebugViewerEditorManager.RegisterMode<TestCustomMode>(MODE_NAME, order); } /// <summary> /// 在点击Clear按钮时被调用 /// </summary> public override void Clear() { base.Clear(); UnityDebugViewerLogger.Log("Clear", MODE_NAME); } /// <summary> /// 在下拉列表中选择当前的模式时被调用 /// </summary> public override void OnGUI() { base.OnGUI(); if (GUILayout.Button(new GUIContent("Add Log"), EditorStyles.toolbarButton)) { UnityDebugViewerLogger.Log("Add Log", MODE_NAME); } } /// <summary> /// 在脚本开始编译时被调用 /// </summary> public override void StartCompiling() { base.StartCompiling(); UnityDebugViewerLogger.Log("StartCompiling", MODE_NAME); } } }



