time:20210909,说实话新版本的unity的console都已经把可以追踪的堆栈行,都列出来了。可以直接定位到。这篇文章其实已经没有意义了。但是这篇文章的内容,还是可以做学习之用。UnityEditor.Callbacks.OnOpenAssetAttribute的事件还是可以做其他用的。
Unity的Console窗口双击重新定向脚本。
因为有时候会自己写脚本 比如输出 Debug.Log 会有不同的颜色, 或者Debug.Log 要向服务器发送数据。 有时候不是用Application HandleLog的方法,会自己写一个DebugEx类,调用unity的Debug。
那么在 Console双击信息的时候,会定位到 Debug调用的位置,而不是 DebugEx调用的位置,这篇脚本 是做重新定位双击打开脚本位置的
附带一些注释。
引用了别人的一篇定位脚本,做了修改。。。引用了谁的已经不记得了。Sorry。
/*
* By: Fox.Huang 黄文叶, Date:2018.12.18
*/
using System;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEngine;
public class DebugCodeLocation
{
#if UNITY_EDITOR
// 处理asset打开的callback函数
[UnityEditor.Callbacks.OnOpenAssetAttribute(0)]
static bool OnOpenAsset(int instance, int line)
{
// 自定义函数,用来获取log中的stacktrace,定义在后面。
string stack_trace = GetStackTrace();
// 通过stacktrace来定位是否是我们自定义的log,我的log中有特殊文字[FoxLog],很好识别
if (!string.IsNullOrEmpty(stack_trace)) // 可以自定义标签 在这里添加;原有代码混乱不做修改,需要自己定位;
{
string strLower = stack_trace.ToLower();
if (strLower.Contains("[foxlog]"))
{
Match matches = Regex.Match(stack_trace, @"\(at(.+)\)", RegexOptions.IgnoreCase);
string pathline = "";
if (matches.Success)
{
pathline = matches.Groups[1].Value;
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 = 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
matches = matches.NextMatch(); // 向上再提高一层 做进入;
这一行的作用是 选择你要的堆栈信息是哪一行
程序学无止尽。
欢迎大家沟通,有啥不明确的,或者不对的,也可以和我私聊
我的QQ 334524067 神一般的狄狄