目录
[TOC]
一、通用消息打印接口
1.简介
将消息打印模块封装一层,并对外提供消息打印接口。如此一来通过封装可以为消息打印提供更多自定义空间。
比如:
- 增加多个消息通道(Channel)每个通道之间互不干扰,可以为不同类型的消息提供不同的消息打印方法;
- 为整个消息打印模块提供统一的开关,从编译层面控制消息打印,可提升实机运行效率。
通用消息打印模块集成在常用工具中(HTUtility)
2.使用方式
步骤:
-
Step1.点击菜单栏:“HTUtility/7.LoggerSwitch” 用于开关消息打印
开启之后,控制台消息会显示:
-
Step2.为不同的消息通道(Channel)实现不同的消息监听对象
public class UnityDebugListener : ILoggerListener { public void Log(string msg) { Debug.Log(msg); } } public class UnityWarningListener : ILoggerListener { public void Log(string msg) { Debug.LogWarning(msg); } } public class UnityErrorListener : ILoggerListener { public void Log(string msg) { Debug.LogError(msg); } }
-
Step3.初始化消息打印模块,并为其注册消息打印监听
UnityDebugListener unityDebugListener = new UnityDebugListener(); UnityWarningListener unityWarningListener = new UnityWarningListener(); UnityErrorListener unityErrorListener = new UnityErrorListener(); Logger.Instance.Init(true); Logger.Instance.AddListener(Logger.Channel.INFO, unityDebugListener); Logger.Instance.AddListener(Logger.Channel.TODO, unityDebugListener); Logger.Instance.AddListener(Logger.Channel.DEBUG, unityDebugListener); Logger.Instance.AddListener(Logger.Channel.WARNING, unityWarningListener); Logger.Instance.AddListener(Logger.Channel.ERROR, unityErrorListener);
-
Step4.可以使用自定义消息打印了
Logger.Info("测试 Logger"); Logger.Todo("测试 Logger"); Logger.Debug("测试 Logger"); Logger.Warning("测试 Logger"); Logger.Error("测试 Logger");
3.开关原理
为消息打印自定义了宏编译#define LOGGER_OPEN
。
当消息打印功能关闭时:
当消息打印功能开启时:
4.代码
普通类的单例模板:
/****************************************************
文件:HTSingleton.cs
作者:HuskyT
邮箱:1005240602@qq.com
日期:2020/3/25 14:41:19
功能:普通单例模板
*****************************************************/
namespace HTUtility
{
public class HTSingleton<T> where T : class, new()
{
private static T mInstance = null;
public static T Instance
{
get
{
if (mInstance == null)
{
mInstance = new T();
}
return mInstance;
}
}
}
}
HTLogger
/****************************************************
文件:HTLogger.cs
作者:HuskyT
邮箱:1005240602@qq.com
日期:2020/3/25 14:4:3
功能:打印消息接口
*****************************************************/
//#define LOGGER_OPEN
using System;
namespace HTUtility
{
/*
* 使用方法:
* 1.新建 Class 实现 ILoggerListener 接口,实现 Log 方法
* 2.初始化 HTLogger
* 3.向 HTLogger 中不同的 Channel 分别添加 LoggerListener 监听
* 4.在菜单栏“HTUtility/6.LoggerSwitch”中开启(切换)Logger 开关
*/
public interface ILoggerListener
{
void Log(string msg);
}
public class HTLogger : HTSingleton<HTLogger>
{
public enum Channel
{
Default = 0,
//打印信息(程序正常运行的信息)
Info,
//待完成的信息
Todo,
//debug时输出的信息
Debug,
//警告信息
Warning,
//错误信息
Error,
}
private static bool mHasInit = false;
//是否需要包装 消息 (给消息加上 日期 和 Channel)
private static bool mNeedPackageMsg = false;
private static bool[] mChannelEnableArray;
private static ILoggerListener[] mChannelListenerArray;
/// <summary>
/// 初始化,默认开启所有频道
/// </summary>
public void Init(bool needPackageMsg = true)
{
mChannelEnableArray = new bool[Enum.GetValues(typeof(Channel)).Length];
mChannelListenerArray = new ILoggerListener[Enum.GetValues(typeof(Channel)).Length];
//默认初始开启所有信息打印通道
for (int i = 0; i < mChannelEnableArray.Length; i++)
{
mChannelEnableArray[i] = true;
}
mNeedPackageMsg = needPackageMsg;
mHasInit = true;
}
/// <summary>
/// 重置
/// </summary>
public void Reset()
{
if (mHasInit == false) return;
for (int i = 0; i < mChannelListenerArray.Length; i++)
{
RemoveListener((Channel)i);
}
mChannelListenerArray = null;
mChannelEnableArray = null;
mNeedPackageMsg = false;
mHasInit = false;
}
/// <summary>
/// 设置频道开关状态
/// </summary>
/// <param 频道="channel"></param>
/// <param 开关状态="state"></param>
public void SetChannelState(Channel channel, bool state)
{
if (mHasInit == false) return;
mChannelEnableArray[(int)channel] = state;
}
public void AddListener(Channel channel, ILoggerListener listener)
{
if (mHasInit == false) return;
if (mChannelEnableArray[(int)channel] == false) return;
mChannelListenerArray[(int)channel] = listener;
}
public void RemoveListener(Channel channel)
{
if (mHasInit == false) return;
mChannelListenerArray[(int)channel] = null;
}
#region 打印消息
public static void Info(string msg)
{
#if LOGGER_OPEN
LogMsg(msg, Channel.Info, mNeedPackageMsg);
#endif
}
public static void Todo(string msg)
{
#if LOGGER_OPEN
LogMsg(msg, Channel.Todo, mNeedPackageMsg);
#endif
}
public static void Debug(string msg)
{
#if LOGGER_OPEN
LogMsg(msg, Channel.Debug, mNeedPackageMsg);
#endif
}
public static void Warning(string msg)
{
#if LOGGER_OPEN
LogMsg(msg, Channel.Warning, mNeedPackageMsg);
#endif
}
public static void Error(string msg)
{
#if LOGGER_OPEN
LogMsg(msg, Channel.Error, mNeedPackageMsg);
#endif
}
public static void LogMsg(string msg, Channel channel, bool needPackageMsg)
{
if (mHasInit == false) return;
if (mChannelEnableArray[(int)channel] == false) return;
ILoggerListener logger = mChannelListenerArray[(int)channel];
if (logger == null) return;
string message = msg;
if (needPackageMsg)
message = PackageMsg(msg, channel);
logger.Log(message);
Console.WriteLine(message);
}
#endregion
/// <summary>
/// 包装信息
/// </summary>
/// <param 信息="msg"></param>
/// <param 频道="channel"></param>
/// <returns></returns>
private static string PackageMsg(string msg, Channel channel)
{
return string.Format("({0})[{1}]:{2}", DateTime.Now.ToString(), channel, msg);
}
}
}
LoggerSwitchMenu
/****************************************************
文件:LoggerSwitchMenu.cs
作者:HuskyT
邮箱:1005240602@qq.com
日期:2020/3/25 15:55:31
功能:消息打印开关(决定 HTLogger 是否参与编译)
*****************************************************/
using UnityEngine;
using UnityEditor;
using System.IO;
namespace HTUtility
{
public class LoggerSwitchMenu : MonoBehaviour
{
public enum LoggerModeEnum
{
//初始未设置时的默认值
Default = 0,
//关闭打印消息
Close = 1,
//开启打印消息
Open = 2,
}
/// <summary>
/// 使用 EditorPrefs 存储的 key 值
/// </summary>
private const string LOGGER_MODE_KEY = "Logger Mode";
/// <summary>
/// 菜单路径
/// </summary>
private const string LOGGER_SWITCH_MENU_PATH = "HTUtility/7.LoggerSwitch";
/// <summary>
/// HTLogger 脚本路径
/// </summary>
private static string mLoggerScriptPath = Application.dataPath + "/HTUtility/7-HTLogger/HTLogger.cs";
/// <summary>
/// LoggerMode 在未设置的时候默认值为 0
/// </summary>
private static LoggerModeEnum mLoggerMode = LoggerModeEnum.Default;
/// <summary>
/// 打印消息模式
/// (此时可打印消息,若关闭打印消息功能,则不会编译,以优化性能)
/// </summary>
private static LoggerModeEnum LoggerMode
{
get
{
//第一次设置 LoggerMode
if (mLoggerMode == LoggerModeEnum.Default)
{
//获取存储的 LoggerMode 值,默认为 Close
mLoggerMode = (LoggerModeEnum)EditorPrefs.GetInt(LOGGER_MODE_KEY, (int)LoggerModeEnum.Close);
}
return mLoggerMode;
}
set
{
mLoggerMode = value;
EditorPrefs.SetInt(LOGGER_MODE_KEY, (int)value);
}
}
/// <summary>
/// 切换 LoggerMode
/// </summary>
[MenuItem(LOGGER_SWITCH_MENU_PATH, false, 7)]
private static void SwitchLoggerMode()
{
LoggerMode = LoggerMode == LoggerModeEnum.Open ? LoggerModeEnum.Close : LoggerModeEnum.Open;
//若为打印消息模式:
if (LoggerMode == LoggerModeEnum.Open)
{
//读取 HTLogger 脚本
string[] contents = File.ReadAllLines(mLoggerScriptPath);
for (int i = 0; i < contents.Length; i++)
{
if (contents[i].StartsWith("//#define"))
{
if (contents[i].Contains("LOGGER_OPEN"))
{
contents[i] = "#define LOGGER_OPEN";
break;
}
}
}
File.WriteAllLines(mLoggerScriptPath, contents);
}
//若为关闭打印消息模式:
else
{
//读取 HTLogger 脚本
string[] contents = File.ReadAllLines(mLoggerScriptPath);
for (int i = 0; i < contents.Length; i++)
{
if (contents[i].StartsWith("#define"))
{
if (contents[i].Contains("LOGGER_OPEN"))
{
contents[i] = "//#define LOGGER_OPEN";
break;
}
}
}
File.WriteAllLines(mLoggerScriptPath, contents);
}
AssetDatabase.Refresh();
Debug.Log("自定义消息打印功能:" + LoggerMode);
}
/// <summary>
/// 切换 LoggerSwitch 的验证方法
/// 每次编译都会执行此方法
/// </summary>
[MenuItem(LOGGER_SWITCH_MENU_PATH, true, 7)]
private static bool SwitchLoggerModeValidate()
{
bool openLogger = LoggerMode == LoggerModeEnum.Open ? true : false;
//将菜单设置成可切换状态
//参数(菜单,依据什么切换)
Menu.SetChecked(LOGGER_SWITCH_MENU_PATH, openLogger);
return true;
}
}
}
测试代码
/****************************************************
文件:UnityLoggerListener.cs
作者:HuskyT
邮箱:1005240602@qq.com
日期:2020/3/25 15:19:55
功能:例子:展示如何在 Unity 中使用 HTLogger
*****************************************************/
using UnityEngine;
namespace HTUtility.Example
{
public class UnityLoggerExample : MonoBehaviour
{
public class UnityDebugListener : ILoggerListener
{
public void Log(string msg)
{
Debug.Log(msg);
}
}
public class UnityWarningListener : ILoggerListener
{
public void Log(string msg)
{
Debug.LogWarning(msg);
}
}
public class UnityErrorListener : ILoggerListener
{
public void Log(string msg)
{
Debug.LogError(msg);
}
}
private void Start()
{
UnityDebugListener unityDebugListener = new UnityDebugListener();
UnityWarningListener unityWarningListener = new UnityWarningListener();
UnityErrorListener unityErrorListener = new UnityErrorListener();
HTLogger.Instance.Init(true);
HTLogger.Instance.AddListener(HTLogger.Channel.Info, unityDebugListener);
HTLogger.Instance.AddListener(HTLogger.Channel.Todo, unityDebugListener);
HTLogger.Instance.AddListener(HTLogger.Channel.Debug, unityDebugListener);
HTLogger.Instance.AddListener(HTLogger.Channel.Warning, unityWarningListener);
HTLogger.Instance.AddListener(HTLogger.Channel.Error, unityErrorListener);
HTLogger.Info("测试 Logger 成功!");
HTLogger.Todo("测试 Logger 成功!");
HTLogger.Debug("测试 Logger 成功!");
HTLogger.Warning("测试 Logger 成功!");
HTLogger.Error("测试 Logger 成功!");
}
}
}
运行结果: