Unity控制台日志开启重定向

在Unity中,一般都会自己手动封装一次日志,或者自定义一些日志输出,比如lua代码的日志输出,双击开启时我们希望重新定向的其他的文件,而不是封装代码里,这里要用到的主要是[OnOpenAssetAttribute(0)],每次文件开启时,先执行自定义的代码,代码里自己重定向文件和行数,然后再选择开启。对于Unity控制台,我们还要用反射取得对应的日志内容。
直接上代码,使用时直接修改logCSName变量,将自己封装的日志类写入即可。


using System.Reflection;
using UnityEditor;
using System;
using UnityEditor.Callbacks;


public class LogRedirect
{
    private const string logCSName = "MyLog.cs";
    private static object logListView;
    private static EditorWindow consoleWindow;
    private static FieldInfo logListViewCurrentRow;
    private static MethodInfo LogEntriesGetEntry;
    private static object logEntry;
    private static FieldInfo logEntryCondition;
    private static int openInstanceID;
    private static int openLine;

    private static bool GetConsoleWindowListView()
    {
        if (logListView == null)
        {
            Assembly unityEditorAssembly = Assembly.GetAssembly(typeof(EditorWindow));
            Type consoleWindowType = unityEditorAssembly.GetType("UnityEditor.ConsoleWindow");
            FieldInfo fieldInfo = consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
            consoleWindow = fieldInfo.GetValue(null) as EditorWindow;

            if (consoleWindow == null)
            {
                logListView = null;
                return false;
            }

            FieldInfo listViewFieldInfo = consoleWindowType.GetField("m_ListView", BindingFlags.Instance | BindingFlags.NonPublic);
            logListView = listViewFieldInfo.GetValue(consoleWindow);
            logListViewCurrentRow = listViewFieldInfo.FieldType.GetField("row", BindingFlags.Instance | BindingFlags.Public);

            Type logEntriesType = unityEditorAssembly.GetType("UnityEditorInternal.LogEntries");
            LogEntriesGetEntry = logEntriesType.GetMethod("GetEntryInternal", BindingFlags.Static | BindingFlags.Public);
            Type logEntryType = unityEditorAssembly.GetType("UnityEditorInternal.LogEntry");
            logEntry = Activator.CreateInstance(logEntryType);
            logEntryCondition = logEntryType.GetField("condition", BindingFlags.Instance | BindingFlags.Public);
        }

        return true;
    }


    private static string GetListViewRowCount(ref int line)
    {
        int row = (int)logListViewCurrentRow.GetValue(logListView);
        LogEntriesGetEntry.Invoke(null, new object[] { row, logEntry });
        string condition = logEntryCondition.GetValue(logEntry) as string;

        int index = condition.IndexOf(logCSName);
        if(index < 0)//不是经过我们封装的日志
        {
            return null;
        }

        int lineIndex = condition.IndexOf(")", index);
        condition = condition.Substring(lineIndex + 2);
        index = condition.IndexOf(".cs:");

        if (index >= 0)
        {
            int lineStartIndex = condition.IndexOf(")");
            int lineEndIndex = condition.IndexOf(")", index);
            string _line = condition.Substring(index + 4, lineEndIndex - index - 4);
            Int32.TryParse(_line, out line);

            condition = condition.Substring(0,index);
            int startIndex = condition.LastIndexOf("/");

            string fileName = condition.Substring(startIndex+1);
            fileName += ".cs";
            return fileName;
        }

        return null;
    }

    [OnOpenAssetAttribute(0)]
    public static bool OnOpenAsset(int instanceID, int line)
    {
        if (!EditorWindow.focusedWindow.titleContent.text.Equals("Console"))//只对控制台的开启进行重定向
            return false;

        //UnityEngine.Object assetObj = EditorUtility.InstanceIDToObject(instanceID);
        //Type assetType = assetObj.GetType();
        //if(assetType != typeof(UnityEditor.MonoScript))//只对开启的脚本进行重定向
        //{
        //    return false;
        //}

        if (openInstanceID == instanceID && openLine == line)
        {
            openInstanceID = -1;
            openLine = -1;
            return false;
        }
        openInstanceID = instanceID;
        openLine = line;

        if (!GetConsoleWindowListView())
        {
            return false;
        }


        string fileName = GetListViewRowCount(ref line);

        if (fileName == null)
        {
            return false;
        }

        if (fileName.EndsWith(".cs"))
        {
            string filter = fileName.Substring(0, fileName.Length - 3);
            filter += " t:MonoScript";
            string[] searchPaths = AssetDatabase.FindAssets(filter);

            for (int i = 0; i < searchPaths.Length; i++)
            {
                string path = AssetDatabase.GUIDToAssetPath(searchPaths[i]);

                if (path.EndsWith(fileName))
                {
                    UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(MonoScript));
                    AssetDatabase.OpenAsset(obj, line);
                    return true;
                }
            }
        }


        return false;
    }
}

版权声明:本文为suifcd原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。