Unity Log 跳转重定向
Hello大家好,这里VimalaEric,今天给大家介绍一个实用脚本 UnityConsoler 跳转重定向。
为何要写这个重定向?
因为有时候会自己写脚本打log,从而实现如输出不同的颜色、Release宏定义、 或者Debug.Log 要向服务器发送数据等。 有时候会自己写一个DebugExtension类,调用unity的Debug的同时封装一些我们需要的内容在上面。
那么在 Console双击信息的时候,会定位到 Debug调用的位置,而不是 DebugEx调用的位置,这篇脚本 是做重新定位双击打开脚本位置的。
开始
在开始之前,首先感谢 @神一般的狄狄 带来的思路。我也是在做公司架构的时候发现这个问题,遂找到了这篇文章。https://blog.csdn.net/qq_37776196/article/details/85324348
基本逻辑如其所示一般,然而在使用时我稍作改动。
1来兼容了对更深层Log的点击重定向。
2来增加了部分注释,微调了部分判断是否属于LogExtension 的逻辑。
将代码贴在下面,以供大家使用。
/*
* CopyRight By VimalaEric & Fox.Huang
* 2024.4.28
*/
using UnityEngine;
using System;
using System.Reflection;
using System.Text.RegularExpressions;
/// <summary>
/// Unity Log重定向。编辑器下,点击log跳转到代码位置
/// </summary>
public class ConsolerRedirection
{
#if UNITY_EDITOR
/// <summary>
/// 最大匹配检索深度
/// </summary>
private const int MaxRegexMatch = 20;
// 处理asset打开的callback函数
[UnityEditor.Callbacks.OnOpenAssetAttribute(0)]
static bool OnOpenAsset(int instance, int line)
{
// 自定义函数,用来获取stacktrace
string stack_trace = GetStackTrace();
// 通过stacktrace来判断是否是自定义Log
if (!string.IsNullOrEmpty(stack_trace))
{
if (stack_trace.StartsWith("* "))//这里的“* ”是从堆栈中筛选自定义的Log
{
//匹配所有Log行
Match matches = Regex.Match(stack_trace, @"\(at(.+)\)", RegexOptions.IgnoreCase);
string pathline = "";
if (matches.Success)
{
/* 找到跳转目标层:
* 需要分别判断点击为首层还是其它层。
* 首层时:跳过自定义Log层,向下一层跳转。
* 其它层:直接跳转。
*/
if (matches.Groups[1].Value.EndsWith(line.ToString())) //首层
{
matches = matches.NextMatch();
}
else
{
for (int i = 0; i < MaxRegexMatch; i++) //其他层
{
if (matches.Groups[1].Value.EndsWith(line.ToString()))
break;
matches = matches.NextMatch();
}
}
//跳转逻辑
if (matches.Success)
{
pathline = matches.Groups[1].Value;
pathline = pathline.Replace(" ", "");
//找到代码及行数
int split_index = pathline.LastIndexOf(":");
string path = pathline.Substring(0, split_index);
line = Convert.ToInt32(pathline.Substring(split_index + 1));
string fullpath = Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("Assets"));
fullpath += path;
string strPath = fullpath.Replace('/', '\\');
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(strPath, line);
}
else
{
Debug.LogError("DebugCodeLocation OnOpenAsset, Error StackTrace");
}
matches = matches.NextMatch();
}
return true;
}
}
return false;
}
static string GetStackTrace()
{
// 找到UnityEditor.EditorWindow的assembly
var assembly_unity_editor = Assembly.GetAssembly(typeof(UnityEditor.EditorWindow));
if (assembly_unity_editor == null) return null;
// 找到类UnityEditor.ConsoleWindow
var type_console_window = assembly_unity_editor.GetType("UnityEditor.ConsoleWindow");
if (type_console_window == null) return null;
// 找到UnityEditor.ConsoleWindow中的成员ms_ConsoleWindow
var field_console_window = type_console_window.GetField("ms_ConsoleWindow",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
if (field_console_window == null) return null;
// 获取ms_ConsoleWindow的值
var instance_console_window = field_console_window.GetValue(null);
if (instance_console_window == null) return null;
// 如果console窗口时焦点窗口的话,获取stacktrace
if ((object)UnityEditor.EditorWindow.focusedWindow == instance_console_window)
{
// 通过assembly获取类ListViewState
var type_list_view_state = assembly_unity_editor.GetType("UnityEditor.ListViewState");
if (type_list_view_state == null) return null;
// 找到类UnityEditor.ConsoleWindow中的成员m_ListView
var field_list_view = type_console_window.GetField("m_ListView",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (field_list_view == null) return null;
// 获取m_ListView的值
var value_list_view = field_list_view.GetValue(instance_console_window);
if (value_list_view == null) return null;
// 找到类UnityEditor.ConsoleWindow中的成员m_ActiveText
var field_active_text = type_console_window.GetField("m_ActiveText",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (field_active_text == null) return null;
// 获得m_ActiveText的值,就是我们需要的stacktrace
string value_active_text = field_active_text.GetValue(instance_console_window).ToString();
return value_active_text;
}
return null;
}
#endif
}