Unity Debug的简单封装

对Unity Debug的简单封装

使用前提:
Project Settings-Player-Other Settings-Script Define Symbols添加 EnableLog,点击Apply
在这里插入图片描述

测试代码:

using MTools.Debuger;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    
    
    public string TAGNAME = "我是日志的标签";

    void Start()
    {
    
    
        Debuger.LogLevel = LogLevel.Error;  //测试,项目中可以通过读取配置文件,更改日志级别

        Debuger.Info("我是一个测试");
        Debuger.Info("NewBehaviourScript", "我是一个测试");
        Debuger.Warn("我是一个测试");
        Debuger.Warn("NewBehaviourScript", "我是一个测试");
        Debuger.Error("我是一个测试");
        Debuger.Error("NewBehaviourScript", "我是一个测试");

        this.Info("我是一个测试2");
        this.Warn("我是一个测试2");
        this.Error("我是一个测试2");
    }
}

效果图:
在这里插入图片描述
日志封装类
Debuger.cs

using System;
using System.IO;
using System.Diagnostics;
using UnityEngine;

namespace MTools.Debuger
{
    
    
    /// <summary>
    /// 日志级别
    /// </summary>
    public enum LogLevel : byte
    {
    
    
        /// <summary>
        /// 信息级别
        /// </summary>
        Info,

        /// <summary>
        /// 警告级别
        /// </summary>
        Warn,

        /// <summary>
        /// 错误级别
        /// </summary>
        Error
    }

    public class Debuger
    {
    
    
        /// <summary>
        /// 日志级别(默认Info)
        /// </summary>
        public static LogLevel LogLevel = LogLevel.Info;
        /// <summary>
        /// 是否使用Unity打印
        /// </summary>
        public static bool UseUnityEngine = true;
        /// <summary>
        /// 是否显示时间
        /// </summary>
        public static bool EnableTime = false;
        /// <summary>
        /// 是否显示堆栈信息
        /// </summary>
        public static bool EnableStack = false;
        /// <summary>
        /// 是否保存到文本
        /// </summary>
        public static bool EnableSave = false;
        /// <summary>
        /// 打印文本流
        /// </summary>
        public static StreamWriter LogFileWriter = null;
        /// <summary>
        /// 日志保存路径(文件夹)
        /// </summary>
        public static string LogFileDir = "";
        /// <summary>
        /// 日志文件名
        /// </summary>
        public static string LogFileName = "";

        //打印格式: {0}-时间 {1}-标签/类名/TAGNAME字段值 {2}-内容
        private static string InfoFormat = "<color=#008000>[Info] {0}<color=#00BFFF>{1}</color> {2}</color>";
        private static string WarnFormat = "<color=#FFFF00>[Warn] {0}<color=#00BFFF>{1}</color> {2}</color>";
        private static string ErrorFormat = "<color=#FF0000>[Error] {0}<color=#00BFFF>{1}</color> {2}</color>";

        private static void Internal_Log(string msg, object context = null)
        {
    
    
            bool useUnityEngine = UseUnityEngine;
            if (useUnityEngine)
            {
    
    
                UnityEngine.Debug.Log(msg, (UnityEngine.Object)context);
            }
            else
            {
    
    
                Console.WriteLine(msg);
            }
        }

        private static void Internal_Warn(string msg, object context = null)
        {
    
    
            bool useUnityEngine = UseUnityEngine;
            if (useUnityEngine)
            {
    
    
                UnityEngine.Debug.LogWarning(msg, (UnityEngine.Object)context);
            }
            else
            {
    
    
                Console.WriteLine(msg);
            }
        }

        private static void Internal_Error(string msg, object context = null)
        {
    
    
            bool useUnityEngine = UseUnityEngine;
            if (useUnityEngine)
            {
    
    
                UnityEngine.Debug.LogError(msg, (UnityEngine.Object)context);
            }
            else
            {
    
    
                Console.WriteLine(msg);
            }
        }

        #region Info
        [Conditional("EnableLog")]
        public static void Info(object message)
        {
    
    
            if (LogLevel >= LogLevel.Info)
            {
    
    
                string msg = string.Format(InfoFormat, GetLogTime(), "", message);
                Internal_Log(msg, null);
                WriteToFile(msg, false);
            }
        }

        [Conditional("EnableLog")]
        public static void Info(object message, object context)
        {
    
    
            if (LogLevel >= LogLevel.Info)
            {
    
    
                string msg = string.Format(InfoFormat, GetLogTime(), "", message);
                Internal_Log(msg, context);
                WriteToFile(msg, false);
            }
        }

        [Conditional("EnableLog")]
        public static void Info(string tag, string message)
        {
    
    
            if (LogLevel >= LogLevel.Info)
            {
    
    
                string msg = string.Format(InfoFormat, GetLogTime(), tag, message);
                Internal_Log(msg, null);
                WriteToFile(msg, false);
            }
        }

        [Conditional("EnableLog")]
        public static void Info(string tag, string format, params object[] args)
        {
    
    
            if (LogLevel >= LogLevel.Info)
            {
    
    
                string msg = string.Format(format, args);
                msg = string.Format(InfoFormat, GetLogTime(), tag, msg);
                Internal_Log(msg, null);
                WriteToFile(msg, false);
            }
        }
        #endregion

        #region Warn
        [Conditional("EnableLog")]
        public static void Warn(object message)
        {
    
    
            if (LogLevel >= LogLevel.Warn)
            {
    
    
                string msg = string.Format(WarnFormat, GetLogTime(), "", message);
                Internal_Warn(msg, null);
                WriteToFile(msg, false);
            }
        }

        [Conditional("EnableLog")]
        public static void Warn(object message, object context)
        {
    
    
            if (LogLevel >= LogLevel.Warn)
            {
    
    
                string msg = string.Format(WarnFormat, GetLogTime(), "", message);
                Internal_Warn(msg, context);
                WriteToFile(msg, false);
            }
        }

        [Conditional("EnableLog")]
        public static void Warn(string tag, string message)
        {
    
    
            if (LogLevel >= LogLevel.Warn)
            {
    
    
                string msg = string.Format(WarnFormat, GetLogTime(), tag, message);
                Internal_Warn(msg, null);
                WriteToFile(msg, false);
            }
        }

        [Conditional("EnableLog")]
        public static void Warn(string tag, string format, params object[] args)
        {
    
    
            if (LogLevel >= LogLevel.Warn)
            {
    
    
                string msg = string.Format(format, args);
                msg = string.Format(WarnFormat, GetLogTime(), tag, msg);
                Internal_Warn(msg, null);
                WriteToFile(msg, false);
            }
        }
        #endregion

        #region Error
        [Conditional("EnableLog")]
        public static void Error(object message)
        {
    
    
            if (LogLevel >= LogLevel.Error)
            {
    
    
                string msg = string.Format(ErrorFormat, GetLogTime(), "", message);
                Internal_Error(msg, null);
                WriteToFile(msg, true);
            }
        }

        [Conditional("EnableLog")]
        public static void Error(object message, object context)
        {
    
    
            if (LogLevel >= LogLevel.Error)
            {
    
    
                string msg = string.Format(ErrorFormat, GetLogTime(), "", message);
                Internal_Error(msg, context);
                WriteToFile(msg, true);
            }
        }

        [Conditional("EnableLog")]
        public static void Error(string tag, string message)
        {
    
    
            if (LogLevel >= LogLevel.Error)
            {
    
    
                string msg = string.Format(ErrorFormat, GetLogTime(), tag, message);
                Internal_Error(msg, null);
                WriteToFile(msg, true);
            }
        }

        [Conditional("EnableLog")]
        public static void Error(string tag, string format, params object[] args)
        {
    
    
            if (LogLevel >= LogLevel.Error)
            {
    
    
                string msg = string.Format(format, args);
                msg = string.Format(ErrorFormat, GetLogTime(), tag, msg);
                Internal_Error(msg, null);
                WriteToFile(msg, true);
            }
        }
        #endregion

        /// <summary>
        /// 获取时间
        /// </summary>
        /// <returns></returns>
        private static string GetLogTime()
        {
    
    
            string result = "";
            if (EnableTime)
            {
    
    
                result = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + " ";
            }
            return result;
        }

        /// <summary>
        /// 序列化打印信息
        /// </summary>
        /// <param name="message">打印信息</param>
        /// <param name="EnableStack">是否开启堆栈打印</param>
        private static void WriteToFile(string message, bool EnableStack = false)
        {
    
    
            bool flag = !EnableSave;
            if (!flag)
            {
    
    
                bool flag2 = LogFileWriter == null;
                if (flag2)
                {
    
    
                    LogFileName = DateTime.Now.GetDateTimeFormats('s')[0].ToString();
                    LogFileName = LogFileName.Replace("-", "_");
                    LogFileName = LogFileName.Replace(":", "_");
                    LogFileName = LogFileName.Replace(" ", "");
                    LogFileName += ".log";
                    bool flag3 = string.IsNullOrEmpty(LogFileDir);
                    if (flag3)
                    {
    
    
                        try
                        {
    
    
                            bool useUnityEngine = UseUnityEngine;
                            if (useUnityEngine)
                            {
    
    
                                LogFileDir = Application.persistentDataPath + "/DebugerLog/";
                            }
                            else
                            {
    
    
                                string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
                                LogFileDir = baseDirectory + "/DebugerLog/";
                            }
                        }
                        catch (Exception ex)
                        {
    
    
                            string msg = string.Format(ErrorFormat, "", "", "获取 Application.persistentDataPath 报错!" + ex.Message);
                            Internal_Error(msg, null);
                            return;
                        }
                    }
                    string path = LogFileDir + LogFileName;
                    try
                    {
    
    
                        bool flag4 = !Directory.Exists(LogFileDir);
                        if (flag4)
                        {
    
    
                            Directory.CreateDirectory(LogFileDir);
                        }
                        LogFileWriter = File.AppendText(path);
                        LogFileWriter.AutoFlush = true;
                    }
                    catch (Exception ex2)
                    {
    
    
                        LogFileWriter = null;
                        string msg = string.Format(ErrorFormat, "", "", "LogToCache()" + ex2.Message + ex2.StackTrace);
                        Internal_Error(msg, null);
                        return;
                    }
                }
                bool flag5 = LogFileWriter != null;
                if (flag5)
                {
    
    
                    try
                    {
    
    
                        LogFileWriter.WriteLine(message);
                        bool flag6 = (EnableStack || Debuger.EnableStack) && UseUnityEngine;
                        if (flag6)
                        {
    
    
                            LogFileWriter.WriteLine(StackTraceUtility.ExtractStackTrace());
                        }
                    }
                    catch (Exception)
                    {
    
    
                    }
                }
            }
        }
    }
}

日志扩展类
DebugerExtension.cs

using System.Reflection;
using System.Diagnostics;

namespace MTools.Debuger
{
    
    
    /// <summary>
    /// 自定义Debuger类的扩展类
    /// </summary>
    public static class DebugerExtension
    {
    
    
        [Conditional("EnableLog")]
        public static void Info(this object obj, string message)
        {
    
    
            if (Debuger.LogLevel >= LogLevel.Info)
            {
    
    
                Debuger.Info(GetLogTag(obj), message);
            }
        }

        [Conditional("EnableLog")]
        public static void Info(this object obj, string format, params object[] args)
        {
    
    
            if (Debuger.LogLevel >= LogLevel.Info)
            {
    
    
                string message = string.Format(format, args);
                Debuger.Info(GetLogTag(obj), message);
            }
        }

        [Conditional("EnableLog")]
        public static void Warning(this object obj, string message)
        {
    
    
            if (Debuger.LogLevel >= LogLevel.Warn)
            {
    
    
                Debuger.Warn(GetLogTag(obj), message);
            }
        }

        [Conditional("EnableLog")]
        public static void Warn(this object obj, string format, params object[] args)
        {
    
    
            if (Debuger.LogLevel >= LogLevel.Warn)
            {
    
    
                string message = string.Format(format, args);
                Debuger.Warn(GetLogTag(obj), message);
            }
        }

        [Conditional("EnableLog")]
        public static void Error(this object obj, string message)
        {
    
    
            if (Debuger.LogLevel >= LogLevel.Error)
            {
    
    
                Debuger.Error(GetLogTag(obj), message);
            }
        }

        [Conditional("EnableLog")]
        public static void Error(this object obj, string format, params object[] args)
        {
    
    
            if (Debuger.LogLevel >= LogLevel.Error)
            {
    
    
                string message = string.Format(format, args);
                Debuger.Error(GetLogTag(obj), message);
            }
        }
        /// <summary>
        /// 获取调用打印的类名称或者标记有TAGNAME的字段
        /// 有TAGNAME字段的,触发类名称用TAGNAME字段对应的赋值
        /// 没有用类的名称代替
        /// </summary>
        /// <param name="obj">触发Log对应的类</param>
        /// <returns></returns>
        private static string GetLogTag(object obj)
        {
    
    
            FieldInfo field = obj.GetType().GetField("TAGNAME");
            bool flag = field != null;
            string result;
            if (flag)
            {
    
    
                result = (string)field.GetValue(obj);
            }
            else
            {
    
    
                result = obj.GetType().Name;
            }
            return result;
        }
    }
}

日志拦截器, 实现Unity中Console窗口双击跳转到合理的位置
LogIntercepter.cs

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

namespace M.Editor
{
    
    
    /// <summary>
    /// 日志拦截器
    /// </summary>
    internal sealed class LogIntercepter
    {
    
    
        private static LogIntercepter _current;
        private static LogIntercepter Current
        {
    
    
            get
            {
    
    
                if (_current == null)
                {
    
    
                    _current = new LogIntercepter();
                }
                return _current;
            }
        }

        private Type _consoleWindowType;
        private FieldInfo _activeTextInfo;
        private FieldInfo _consoleWindowInfo;
        private MethodInfo _setActiveEntry;
        private object[] _setActiveEntryArgs;
        private object _consoleWindow;

        private LogIntercepter()
        {
    
    
            _consoleWindowType = Type.GetType("UnityEditor.ConsoleWindow,UnityEditor");
            _activeTextInfo = _consoleWindowType.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic);
            _consoleWindowInfo = _consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
            _setActiveEntry = _consoleWindowType.GetMethod("SetActiveEntry", BindingFlags.Instance | BindingFlags.NonPublic);
            _setActiveEntryArgs = new object[] {
    
     null };
        }

        [OnOpenAsset]
        private static bool OnOpenAsset(int instanceID, int line)
        {
    
    
            UnityEngine.Object instance = EditorUtility.InstanceIDToObject(instanceID);
            if (AssetDatabase.GetAssetOrScenePath(instance).EndsWith(".cs"))
            {
    
    
                return Current.OpenAsset();//双击会触发这里
            }
            return false;
        }

        private bool OpenAsset()
        {
    
    
            string stackTrace = GetStackTrace();
            if (stackTrace != "")
            {
    
    
                //结合条件  可以用来过滤是否使用了原始接口还是自定义的
                if (stackTrace.Contains("[Info]") || stackTrace.Contains("[Warn]") || stackTrace.Contains("[Error]"))
                {
    
    
                    string[] paths = stackTrace.Split('\n');

                    for (int i = 0; i < paths.Length; i++)
                    {
    
    
                        //过滤日志封装类和日志扩展类
                        if (!paths[i].Contains("Debuger.cs") && !paths[i].Contains("DebugerExtension.cs") && paths[i].Contains(" (at "))
                        {
    
    
                            return OpenScriptAsset(paths[i]);
                        }
                    }
                }
            }
            return false;
        }

        private bool OpenScriptAsset(string path)
        {
    
    
            int startIndex = path.IndexOf(" (at ") + 5;
            int endIndex = path.IndexOf(".cs:") + 3;
            string filePath = path.Substring(startIndex, endIndex - startIndex);
            string lineStr = path.Substring(endIndex + 1, path.Length - endIndex - 2);
            TextAsset asset = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath);
            if (asset != null)
            {
    
    
                int line;
                if (int.TryParse(lineStr, out line))
                {
    
    
                    object consoleWindow = GetConsoleWindow();
                    _setActiveEntry.Invoke(consoleWindow, _setActiveEntryArgs);

                    EditorGUIUtility.PingObject(asset);
                    AssetDatabase.OpenAsset(asset, line);
                    return true;
                }
            }
            return false;
        }

        private string GetStackTrace()
        {
    
    
            object consoleWindow = GetConsoleWindow();

            if (consoleWindow != null)
            {
    
    
                if (consoleWindow == EditorWindow.focusedWindow as object)
                {
    
    
                    object value = _activeTextInfo.GetValue(consoleWindow);
                    return value != null ? value.ToString() : "";
                }
            }
            return "";
        }

        private object GetConsoleWindow()
        {
    
    
            if (_consoleWindow == null)
            {
    
    
                _consoleWindow = _consoleWindowInfo.GetValue(null);
            }
            return _consoleWindow;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44238530/article/details/128155664