【Unity】通用的Debugger日志模块

模块代码整理自 http://gad.qq.com/lore/catalog/10007

Debugger类。提供打印日志的静态方法。

using System;
using System.IO;

namespace UnityEngine
{
    /// <summary>
    /// 系统日志模块
    /// </summary>
    public class Debugger
    {
        public static bool EnableLog;           // 是否启用日志,仅可控制普通级别的日志的启用与关闭,LogError和LogWarn都是始终启用的。
        public static bool EnableTime = true;
        public static bool EnableSave = false;  // 是否允许保存日志,即把日志写入到文件中
        public static bool EnableStack = false;
        public static string LogFileDir = Application.persistentDataPath + "/DebuggerLog/";
        public static string LogFileName = "";
        public static string Prefix = "> ";     // 用于与Unity默认的系统日志做区分。本日志系统输出的日志头部都会带上这个标记。
        public static StreamWriter LogFileWriter = null;
        public static bool UseUnityEngine;

        private static string GetLogText(string tag, string message)
        {
            string str = "";
            if (EnableTime)
            {
                str = DateTime.Now.ToString("HH:mm:ss.fff") + " ";
            }
            return (str + tag + "::" + message);
        }

        private static string GetLogTime()
        {
            string str = "";
            if (EnableTime)
            {
                str = DateTime.Now.ToString("HH:mm:ss.fff") + " ";
            }
            return str;
        }

        public static void Log(object message)
        {
            if (!Debugger.EnableLog)
                return;

            string str = GetLogTime() + message;
            Debug.Log(Prefix + str, null);
            LogToFile("[I]" + str, false);
        }

        public static void Log(object message, Object context)
        {
            if (!Debugger.EnableLog)
                return;

            string str = GetLogTime() + message;
            Debug.Log(Prefix + str, context);
            LogToFile("[I]" + str, false);
        }

        public static void Log(string tag, string message)
        {
            if (!Debugger.EnableLog)
                return;

            message = GetLogText(tag, message);
            Debug.Log(Prefix + message, null);
            LogToFile("[I]" + message, false);
        }

        public static void Log(string tag, string format, params object[] args)
        {
            if (!Debugger.EnableLog)
                return;

            string logText = GetLogText(tag, string.Format(format, args));
            Debug.Log(Prefix + logText, null);
            LogToFile("[I]" + logText, false);
        }

        public static void LogError(object message)
        {
            string str = GetLogTime() + message;
            Debug.Log(Prefix + str, null);
            LogToFile("[E]" + str, true);
        }

        public static void LogError(object message, Object context)
        {
            string str = GetLogTime() + message;
            Debug.Log(Prefix + str, context);
            LogToFile("[E]" + str, true);
        }

        public static void LogError(string tag, string message)
        {
            message = GetLogText(tag, message);
            Debug.Log(Prefix + message, null);
            LogToFile("[E]" + message, true);
        }

        public static void LogError(string tag, string format, params object[] args)
        {
            string logText = GetLogText(tag, string.Format(format, args));
            Debug.Log(Prefix + logText, null);
            LogToFile("[E]" + logText, true);
        }

        /// <summary>
        /// 将日志写入到文件中
        /// </summary>
        /// <param name="message"></param>
        /// <param name="EnableStack"></param>
        private static void LogToFile(string message, bool EnableStack = false)
        {
            if (!Debugger.EnableSave)
                return;

            if (LogFileWriter == null)
            {
                LogFileName = DateTime.Now.GetDateTimeFormats('s')[0].ToString();
                LogFileName = LogFileName.Replace("-", "_");
                LogFileName = LogFileName.Replace(":", "_");
                LogFileName = LogFileName.Replace(" ", "");
                LogFileName = LogFileName + ".log";
                if (string.IsNullOrEmpty(LogFileDir))
                {
                    try
                    {
                        if (UseUnityEngine)
                        {
                            LogFileDir = Application.persistentDataPath + "/DebuggerLog/";
                        }
                        else
                        {
                            LogFileDir = AppDomain.CurrentDomain.BaseDirectory + "/DebuggerLog/";
                        }
                    }
                    catch (Exception exception)
                    {
                        Debug.Log(Prefix + "获取 Application.persistentDataPath 报错!" + exception.Message, null);
                        return;
                    }
                }
                string path = LogFileDir + LogFileName;
                try
                {
                    if (!Directory.Exists(LogFileDir))
                    {
                        Directory.CreateDirectory(LogFileDir);
                    }
                    LogFileWriter = File.AppendText(path);
                    LogFileWriter.AutoFlush = true;
                }
                catch (Exception exception2)
                {
                    LogFileWriter = null;
                    Debug.Log("LogToCache() " + exception2.Message + exception2.StackTrace, null);
                    return;
                }
            }
            if (LogFileWriter != null)
            {
                try
                {
                    LogFileWriter.WriteLine(message);
                    if ((EnableStack || Debugger.EnableStack) && UseUnityEngine)
                    {
                        LogFileWriter.WriteLine(StackTraceUtility.ExtractStackTrace());
                    }
                }
                catch (Exception)
                {
                }
            }
        }

        public static void LogWarning(object message)
        {
            string str = GetLogTime() + message;
            Debug.Log(Prefix + str, null);
            LogToFile("[W]" + str, false);
        }

        public static void LogWarning(object message, Object context)
        {
            string str = GetLogTime() + message;
            Debug.Log(Prefix + str, context);
            LogToFile("[W]" + str, false);
        }

        public static void LogWarning(string tag, string message)
        {
            message = GetLogText(tag, message);
            Debug.Log(Prefix + message, null);
            LogToFile("[W]" + message, false);
        }

        public static void LogWarning(string tag, string format, params object[] args)
        {
            string logText = GetLogText(tag, string.Format(format, args));
            Debug.Log(Prefix + logText, null);
            LogToFile("[W]" + logText, false);
        }

    }
}

DebuggerExtension类。采用C#的扩展方法特性,使所有System.Object子类获得了打印日志的函数功能。

using System.Diagnostics;
using System.Reflection;
using UnityEngine;

namespace UnityEngine
{
    /// <summary>
    /// 日志模块的扩展类
    /// </summary>
    public static class DebuggerExtension
    {
        /// <summary>
        /// LogTag是调用打印日志的类中自定义的常量字符串,通常情况下LogTag是类名。
        /// 用LogTag可以直观地看出这条日志是哪个类输出的。
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static string GetLogTag(object obj)
        {
            FieldInfo field = obj.GetType().GetField("LOG_TAG");
            if (field != null)
            {
                return (string)field.GetValue(obj);
            }
            return obj.GetType().Name;
        }

        [Conditional("EnableLog")]
        public static void Log(this object obj, string message)
        {
            if (Debugger.EnableLog)
            {
                Debugger.Log(GetLogTag(obj), message);
            }
        }

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

        public static void LogError(this object obj, string message)
        {
            Debugger.LogError(GetLogTag(obj), message);
        }

        public static void LogError(this object obj, string format, params object[] args)
        {
            string message = string.Format(format, args);
            Debugger.LogError(GetLogTag(obj), message);
        }

        public static void LogWarning(this object obj, string message)
        {
            Debugger.LogWarning(GetLogTag(obj), message);
        }

        public static void LogWarning(this object obj, string format, params object[] args)
        {
            string message = string.Format(format, args);
            Debugger.LogWarning(GetLogTag(obj), message);
        }

    }
}

Example测试日志模块。

using UnityEngine;

public class Example_Debugger : MonoBehaviour
{
    void Start()
    {
        Debug.Log("这是Unity默认的日志!");

        Debugger.EnableLog = true;
        Debugger.EnableTime = true;

        Debugger.Log("Debugger.Log");
        Debugger.LogWarning("Debugger.LogWarning");
        Debugger.LogError("Debugger.LogError");

        Debugger.Log("Example_Debugger", "格式化日志: {0}", 123456);
        Debugger.Log("日志保存路径:", Debugger.LogFileDir);

        this.Log("日志扩展类中的方法。该方法需要在Unity编辑器中添加宏命令EnableLog才能被编译!");
    }

}

运行效果:

注意,DebuggerExtension类采用了[Conditional]特性条件编译,被[Conditional]标记的函数需要在Unity编辑器中开启命令宏才能被编译,参考这里

建议将Debugger类和DebuggerExtension类都编译到Debugger.dll中,再放入Unity工程Asset目录下使用。因为如果将Debuger类放到主工程里,在Unity的日志输出窗口Console中点击日志,会跳转到Debuger类中的代码,而我们真正想要跳转到的是调用了Debuger的地方。

 

posted @ 2018-07-04 09:51  霍莉雪特  阅读(2489)  评论(0编辑  收藏  举报