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;
        }
    }
}
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: b'unity debug.drawline' 是一种 Unity 编辑器的调试工具,用于在游戏场景中进行可视化线段的绘制,帮助开发者调试代码和检查游戏逻辑。这个工具可以指定起始点和终止点,也可以设置线段的颜色和宽度等属性。 ### 回答2: Unity Debug.DrawLine是一个非常有用的函数,它能够在场景中绘制一条线来帮助开发人员调试代码或测试某些功能。 使用Debug.DrawLine非常简单,只需在代码中调用它即可。它需要三个参数:起始点、结束点和颜色。你可以根据需要在任何时间调用它,例如在Update方法中,以便在场景中绘制跟随某些用户输入的线,或者在OnGUI方法中绘制GUI元素之外的辅助线。 此外,Debug.DrawLine还接受两个可选参数,使其更加灵活。第一个可选参数是持续时间,它指定线的持续时间(以秒为单位),默认为0。如果您想绘制一个只显示一段时间的线,则可以在调用Debug.DrawLine时指定持续时间。第二个可选参数是深度测试开关。它指定是否在绘制线条时启用深度测试。如果启用,那么线条将只绘制在前面的物体上,不会绘制在后面的物体上。 需要注意的是,Debug.DrawLine只会在编辑器中显示,在发布后的应用程序中不会出现。因此,如果您需要在运行时在当前应用程序中绘制线条,则需要使用其他的方法。但是,Debug.DrawLine为Unity开发者提供了一个非常便捷的工具来快速调试和测试他们的代码。 总的来说,Debug.DrawLine是Unity中非常有用的调试工具,它能够帮助Unity开发人员在开发过程中快速跟踪和解决问题。 ### 回答3: Unity Debug.DrawLine是一种常见的调试工具,它用于帮助开发人员可视化地检查场景中的物体和碰撞器之间的关系。此函数允许你在游戏场景中绘制一条线段以显示对象之间的距离和方向等信息。 这个函数需要四个参数,起点坐标,终点坐标,线段的颜色,以及绘制线段的时间长度。它也可以使用Debug.DrawLine(Vector3 start, Vector3 end, Color color)方法,其中默认的时间是0。 使用Debug.DrawLine时,需要将其放在特定的函数中,如Update()或OnGUI()等中,并在函数体中调用它。当调用函数时,将根据给定的参数在场景中绘制线段,这样就可以看到您想要检查的对象之间的距离和方向。 在调试中,Debug.DrawLine是一个非常有用的工具。它帮助开发人员可视化场景中的关系,并且可以用作代码的一部分,例如在角色行进路线计算中。它可以帮助开发人员快速调试程序,找到问题所在,以便更快地修复问题。 总之,Debug.DrawLine是Unity中常用的调试工具之一。它可以帮助开发人员快速找到问题所在,并且可以非常方便地在场景中可视化检查对象之间的关系。开发人员应该熟练掌握此功能,并在需要时合理使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值