【Unity Consoler Redirection】Unity Log 跳转重定向

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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/581992.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VULHUB复现fastjson1.2.24反序列化漏洞

蚌埠住了&#xff0c;遇到了很多奇奇怪怪的问题。 如果你问我为啥不用kali&#xff0c;我会告诉你&#xff0c;我电脑上的kali装不成docker-compose!我急用了ubuntu如果你问我为啥用ubuntu克隆&#xff0c;我会告诉你&#xff0c;我电脑上的kali不能安装成功java8这个版本如果你…

秋招后端开发面试题 - Java语言基础(下)

目录 Java基础下前言面试题toString() 、String.valueof()、(String)&#xff1f;hashCode() 方法&#xff1f;hashCode 和 equals 方法判断两个对象是否相等&#xff1f;为什么重写 equals 时必须重写 hashCode 方法&#xff1f;String、StringBuffer、StringBuilder?String …

《ESP8266通信指南》9-TCP通信(Arudino开发)

往期 《ESP8266通信指南》8-连接WIFI&#xff08;Arduino开发&#xff09;&#xff08;非常简单&#xff09;-CSDN博客 《ESP8266通信指南》7-Arduino 开发8266的环境配置与示例代码烧录-CSDN博客 《ESP8266通信指南》6-创建TCP服务器&#xff08;AT指令&#xff09;-CSDN博…

asp.net结课作业中遇到的问题解决1

作业要求 实现增删改查导出基本功能。 1、如何设置使得某个背景就是一整个而不是无限填充或者是这个图片的某一部分。 这就要求在设置这一块的时候&#xff0c;长和宽按照背景图片的大小进行设置&#xff0c;比如&#xff1a; 如果&#xff0c;图片的大小不符合你的要求&am…

如何让用户听话?

​福格教授&#xff08;斯坦福大学行为设计实验室创始人&#xff09;通过深入研究人类行为20年&#xff0c;2007年用自己的名子命名&#xff0c;提出了一个行为模型&#xff1a;福格行为模型。 模型表明&#xff1a;人的行为发生&#xff0c;要有做出行为的动机和完成行为的能…

操作系统——优先权算法c++实现

变量描述 测试数据 5 A 0 4 4 B 1 3 2 C 2 5 3 D 3 2 5 E 4 4 1 先来先服务算法 简述 该算法实现非常简单就是对到达时间排个序&#xff0c;然后依次进行即可&#xff0c;对结构体的sort进行了重载 代码 void FCFS() {//先来先服务算法std::cout<<"\n\t\t\t\t\…

字典及GitHub字典爬取工具

红队API接口Fuzz字典可以用于WEB安全&#xff0c;渗透测试&#xff0c;SRC等场景 完整文件已上传知识星球&#xff0c;需要的朋友可加入查看。

STM32应用开发教程进阶--Wi-Fi通信(ESP8266模块:STA、AP、STA+AP)

实现目标 1、熟悉Wi-F、ESP8266模块 2、掌握ESP8266模块共3种工作模式&#xff1a;STA、AP、STAAP的配置 3、具体实现目标&#xff1a;&#xff08;1&#xff09;AT固件烧录&#xff1b;&#xff08;2&#xff09;ESP8266模块STA、AP、STAAP的配置 一、Wi-Fi概述 1、Wi-Fi定…

OpenCV-Python: 强大的计算机视觉库

文章目录 OpenCV-Python: 强大的计算机视觉库背景OpenCV-Python是什么&#xff1f;安装简单的库函数使用方法场景示例人脸检测和识别图像分割目标跟踪 常见问题和解决方案总结 OpenCV-Python: 强大的计算机视觉库 背景 OpenCV (Open Source Computer Vision Library) 是一个开…

OceanBase 助力同方智慧能源,打造安全可靠、高性能的能源数据架构

本文作者&#xff1a;丁泽斌&#xff0c;同方智慧能源数据库工程师 业务背景 作为同方股份有限公司旗下的领军企业&#xff0c;同方智慧能源集团矢志成为全球领先的综合智慧能源解决方案提供商。凭借中核集团和清华大学的科技实力&#xff0c;专注于向建筑、交通、工业、北方供…

Altair® HPCWorks™——高性能计算(HPC)和云平台

Altair HPCWorks™——高性能计算&#xff08;HPC&#xff09;和云平台 强大的计算助力研发增速&#xff0c;Altair HPCWorks™ 使高性能和云计算变得快速、高效和提高有效产出 - 无论您的资源是在本地、云端还是混合环境中。专业地管理 IT 复杂性并支持最新的 AI 工作负载。使…

《QT实用小工具·四十五》可以在界面上游泳的小鱼

1、概述 源码放在文章末尾 该项目实现了灵动的小鱼&#xff0c;可以在界面上跟随鼠标点击自由的游泳&#xff0c;项目demo演示如下所示&#xff1a; 项目部分代码如下所示&#xff1a; #include "magicfish.h" #include <QtMath> #include <QPainter>…

CentOS7安装和升级nginx

文章目录 一 环境准备二 安装nginx三 升级nginx四 注意事项 一 环境准备 公司等保要求修复nginx的应用漏洞&#xff0c;从1.12.2升级到1.20.2版本。 本机操作系统是CentOS7.9&#xff0c;主机IP是192.168.0.201&#xff0c;nginx是在服务器部署而非容器部署。 下列安装和升级…

Springboot + MySQL + html 实现文件的上传、存储、下载、删除

实现步骤及效果呈现如下&#xff1a; 1.创建数据库表&#xff1a; 表名&#xff1a;file_test 存储后的数据&#xff1a; 2.创建数据库表对应映射的实体类&#xff1a; import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.Table…

《R语言与农业数据统计分析及建模》学习——回归分析

一、线性回归 线性回归是一种广泛用于数据分析、预测和建模的技术&#xff0c;可以帮助我们理解变量之间的关系&#xff0c;并进行预测和推断。 1、简单线性回归 简单线性回归是线性回归的一种特殊情况&#xff0c;适用于只有一个自变量和一个因变量的情况。 在R语言中&#x…

QT c++ 代码布局原则 简单例子

本文描述QT c widget代码布局遵循的原则&#xff1a;实中套虚&#xff0c;虚中套实。 本文最后列出了代码下载链接。 在QT6.2.4 msvc2019编译通过。 所谓实是实体组件&#xff1a;比如界面框、文本标签、组合框、文本框、按钮、表格、图片框等。 所谓虚是Layout组件&#x…

IT廉连看——UniApp——样式绑定

IT廉连看——UniApp——样式绑定 一、样式绑定 两种添加样式的方法&#xff1a; 1、第一种写法 写一个class属性&#xff0c;然后将css样式写在style中。 2、第二种写法 直接把style写在class后面 添加一些效果&#xff1a;字体大小 查看效果 证明这样添加样式是没有问题的…

WPF —— MVVM 指令执行不同的任务实例

标签页 设置两个按钮&#xff0c; <Button Content"修改状态" Width"100" Height"40" Background"red"Click"Button_Click"></Button><Button Content"测试"Width"100"Height"40&…

clickhous学习之旅二

接上回继续鼓捣clickhouse 1.常用数据类型 1.1整型 固定长度的整型&#xff0c;包括有符号整型或无符号整型。整型范围(-2n-1~2n-1-1): Int8 - [-128 :127] -->相当于java中的byte Int16-[-32768 :32767] -->相当于java中的short Int32-[-2147483648 :2147483647] -…

最新官方破解版会声会影2024永久序列号和激活码

会声会影2024是一款功能强大的视频编辑软件&#xff0c;它集合了视频剪辑、音频调整、特效添加等多项功能于一身&#xff0c;为用户提供了一个全面且易用的视频制作平台。无论是初学者还是专业视频编辑人员&#xff0c;都能在这款软件中找到满足自己创作需求的工具。 会声会影最…