5评论

控制台日志重定向及Debug封装

萧然 2018-10-10 2.5k浏览
之前利用dll做过一次Debug的封装,后来在使用中感觉不是很方便,如果想要添加或修改封装脚本的代码,需要在改完之后重新生成dll文件。
将Debug封装成dll  http://gad.qq.com/article/detail/287087

后来经“天天向上”大大提示,参考一下两篇博文,利用控制台日志重定向重新做了一次封装:
Unity日志工具——封装,跳转 http://dsqiu.iteye.com/blog/2263664
Unity控制台日志开启重定向 https://blog.csdn.net/suifcd/article/details/72553678
using UnityEngine;
#if UNITY_EDITOR
using System.Reflection;
using UnityEditor;
using System;
using UnityEditor.Callbacks;
#endif
public enum LogColor
{
    red,
    blue,
    green,
    yellow,
    //······
}
// ----- 封装Debug -----
public class Debuger
{
    static bool enable = false;
    public static bool Enable
    {
        get { return enable; }
        set { enable = value; }
    }
    //暂停编辑器
    public static void Break()
    {
        Debug.Break();
    }
    //清空控制台
    public static void Clear()
    {
        Assembly assembly = Assembly.GetAssembly(typeof(SceneView));
        Type logEntries = assembly.GetType("UnityEditor.LogEntries");
        Debug.Log(logEntries);
        MethodInfo clearConsoleMethod = logEntries.GetMethod("Clear");
        clearConsoleMethod.Invoke(new object(), null);
    }
    public static void Log(object message)
    {
        if (enable)
            Debug.Log(message);
    }
    public static void Log(object message, UnityEngine.Object context)
    {
        if (enable)
            Debug.Log(message, context);
    }
    //不同文字颜色
    public static void Log(object message, LogColor color)
    {
        if (enable)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.AppendFormat("<color={0}>{1}</color>", color.ToString(), message);
            Debug.Log(sb);
        }
    }
    //省略重复代码
    //······
}
// ----- Log重定向 -----
#if UNITY_EDITOR
//Log重定向
public class DebugRedirect
{
    const string logCSName = "Debuger.cs";
    static object logListView;
    static object logEntry;
    static FieldInfo logListViewCurrentRow;
    static FieldInfo logEntryCondition;
    static MethodInfo LogEntriesGetEntry;
    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);
            EditorWindow 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");  //内部API变更
            Type logEntriesType = unityEditorAssembly.GetType("UnityEditor.LogEntries");
            LogEntriesGetEntry = logEntriesType.GetMethod("GetEntryInternal", BindingFlags.Static | BindingFlags.Public);
            //Type logEntryType = unityEditorAssembly.GetType("UnityEditorInternal.LogEntry");
            Type logEntryType = unityEditorAssembly.GetType("UnityEditor.LogEntry");
            logEntry = Activator.CreateInstance(logEntryType);
            logEntryCondition = logEntryType.GetField("condition", BindingFlags.Instance | BindingFlags.Public);
        }
        return true;
    }
    static string GetListViewRowCount(ref int line)
    {
        if (!GetConsoleWindowListView())
            return null;
        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, StringComparison.Ordinal);
        //没有封装部分
        if (index < 0)
            return null;
        int lineIndex = condition.IndexOf(")", index, StringComparison.Ordinal);
        condition = condition.Substring(lineIndex + 2);
        index = condition.IndexOf(".cs:", StringComparison.Ordinal);
        if (index >= 0)
        {
            int lineStartIndex = condition.IndexOf(")", StringComparison.Ordinal);
            int lineEndIndex = condition.IndexOf(")", index, StringComparison.Ordinal);
            string _line = condition.Substring(index + 4, lineEndIndex - index - 4);
            Int32.TryParse(_line, out line);
            condition = condition.Substring(0, index);
            int startIndex = condition.LastIndexOf("/", StringComparison.Ordinal);
            string fileName = condition.Substring(startIndex + 1);
            fileName += ".cs";
            return fileName;
        }
        return null;
    }
    static int openInstanceID;
    static int openLine;
    [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;
        string fileName = GetListViewRowCount(ref line);
        if (string.IsNullOrEmpty(fileName) || !fileName.EndsWith(".cs", StringComparison.Ordinal))
            return false;
        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, StringComparison.Ordinal))
            {
                UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(MonoScript));
                AssetDatabase.OpenAsset(obj, line);
                return true;
            }
        }
        return false;
    }
}
#endif