Unity编辑器扩展-ConsoleWindow中的双击日志定位

很多项目都有自己重写Debug.Log的习惯,难免会遇到在Unity的Console窗口中双击日志,但是没法直接跳转到想要看到的代码那一行的时候,解决办法有以下2种:


1、将自己封装的日志类制作成DLL再导入到Unity使用,但是有时候想修改日志类的代码却比较麻烦了~~

2、使用本文提供的LogEditor类来自动定位!。!下面来详细说明下该类吧~~


使用方法:

1、将LogEditor类的脚本放到名字为Editor的目录下(如果没有Editor目录就新建一个吧)

2、在这里修改和添加自己封装过的日志类(路径+类型),支持添加多个封装的日志类


3、现在可以直接在Console窗口中双击日志,就会自动跳转到调用自己封装日志类的代码位置啦~Unity编辑器扩展-ConsoleWindow中的双击日志定位_第1张图片


附上源代码:

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;

namespace shaco
{
    public static class LogEditor
    {
        private class LogEditorConfig
        {
            public string logScriptPath = "";
            public string logTypeName = "";
            public int instanceID = 0;

            public LogEditorConfig(string logScriptPath, System.Type logType)
            {
                this.logScriptPath = logScriptPath;
                this.logTypeName = logType.FullName;
            }
        }

        //Add your custom Log class here
        private static LogEditorConfig[] _logEditorConfig = new LogEditorConfig[]
        {
            new LogEditorConfig("Assets/shaco/Base/Scripts/Unity/Debug/Log.cs", typeof(shaco.Log)),
            new LogEditorConfig("Assets/shaco/Base/Scripts/CSharp/Debug/Log.cs", typeof(shaco.Base.Log))
        };

        [UnityEditor.Callbacks.OnOpenAssetAttribute(-1)]
        private static bool OnOpenAsset(int instanceID, int line)
        {
            for (int i = _logEditorConfig.Length - 1; i >= 0; --i)
            {
                var configTmp = _logEditorConfig[i];
                UpdateLogInstanceID(configTmp);
                if (instanceID == configTmp.instanceID)
                {
                    var statckTrack = GetStackTrace();
                    if (!string.IsNullOrEmpty(statckTrack))
                    {
                        var fileNames = statckTrack.Split('\n');
                        var fileName = GetCurrentFullFileName(fileNames);
                        var fileLine = LogFileNameToFileLine(fileName);
                        fileName = GetRealFileName(fileName);

                        AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath(fileName), fileLine);
                        return true;
                    }
                    break;
                }
            }
            
            return false;
        }

        private static string GetStackTrace()
        {
            var consoleWindowType = typeof(EditorWindow).Assembly.GetType("UnityEditor.ConsoleWindow");
            var fieldInfo = consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
            var consoleWindowInstance = fieldInfo.GetValue(null);

            if (null != consoleWindowInstance)
            {
                if ((object)EditorWindow.focusedWindow == consoleWindowInstance)
                {
                    // Get ListViewState in ConsoleWindow
                    // var listViewStateType = typeof(EditorWindow).Assembly.GetType("UnityEditor.ListViewState");
                    // fieldInfo = consoleWindowType.GetField("m_ListView", BindingFlags.Instance | BindingFlags.NonPublic);
                    // var listView = fieldInfo.GetValue(consoleWindowInstance);

                    // Get row in listViewState
                    // fieldInfo = listViewStateType.GetField("row", BindingFlags.Instance | BindingFlags.Public);
                    // int row = (int)fieldInfo.GetValue(listView);

                    // Get m_ActiveText in ConsoleWindow
                    fieldInfo = consoleWindowType.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic);
                    string activeText = fieldInfo.GetValue(consoleWindowInstance).ToString();

                    return activeText;
                }
            }
            return "";
        }

        private static void UpdateLogInstanceID(LogEditorConfig config)
        {
            if (config.instanceID > 0)
            {
                return;
            }

            var assetLoadTmp = AssetDatabase.LoadAssetAtPath(config.logScriptPath);
            if (null == assetLoadTmp)
            {
                throw new System.Exception("not find asset by path=" + config.logScriptPath);
            }
            config.instanceID = assetLoadTmp.GetInstanceID();
        }

        private static string GetCurrentFullFileName(string[] fileNames)
        {
            string retValue = "";
            int findIndex = -1;

            for (int i = fileNames.Length - 1; i >= 0; --i)
            {
				bool isCustomLog = false;
				for (int j = _logEditorConfig.Length - 1; j >= 0; --j)
				{
					if (fileNames[i].Contains(_logEditorConfig[j].logTypeName))
					{
						isCustomLog = true;
						break;
					}
				}
                if (isCustomLog)
                {
                    findIndex = i;
                    break;
                }
            }

            if (findIndex >= 0 && findIndex < fileNames.Length - 1)
            {
                retValue = fileNames[findIndex + 1];
            }

            return retValue;
        }

        private static string GetRealFileName(string fileName)
        {
            int indexStart = fileName.IndexOf("(at ") + "(at ".Length;
            int indexEnd = ParseFileLineStartIndex(fileName) - 1;

            fileName = fileName.Substring(indexStart, indexEnd - indexStart);
            return fileName;
        }

        private static int LogFileNameToFileLine(string fileName)
        {
            int findIndex = ParseFileLineStartIndex(fileName);
            string stringParseLine = "";
            for (int i = findIndex; i < fileName.Length; ++i)
            {
                var charCheck = fileName[i];
                if (!IsNumber(charCheck))
                {
                    break;
                }
                else
                {
                    stringParseLine += charCheck;
                }
            }

            return int.Parse(stringParseLine);
        }

        private static int ParseFileLineStartIndex(string fileName)
        {
            int retValue = -1;
            for (int i = fileName.Length - 1; i >= 0; --i)
            {
                var charCheck = fileName[i];
                bool isNumber = IsNumber(charCheck);
                if (isNumber)
                {
                    retValue = i;
                }
                else
                {
                    if (retValue != -1)
                    {
                        break;
                    }
                }
            }
            return retValue;
        }

        private static bool IsNumber(char c)
        {
            return c >= '0' && c <= '9';
        }
    }
}

如果感兴趣的话请多多支持下吧~~~

你可能感兴趣的:(Unity编辑器扩展,unity,编辑器,扩展)