使用
// 调试日志
Log.Debug("Hello, world!");
// 信息日志
Log.Info("Hello, world!");
// 警告日志
Log.Warning("Hello, world!");
// 错误日志
Log.Error("Hello, world!");
// 严重错误日志
Log.Fatal("Hello, world!");
分析
Unity脚本
Log
Unity脚本调用该类来打印日志。
(内部就是转发了框架中的 GameFrameworkLog类 )
代码
using GameFramework;
using System.Diagnostics;
namespace UnityGameFramework.Runtime
{
/// <summary>
/// 日志工具集。
/// </summary>
public static class Log
{
/// <summary>
/// 打印调试级别日志,用于记录调试类日志信息。
/// </summary>
/// <param name="message">日志内容。</param>
/// <remarks>仅在带有 DEBUG 预编译选项且带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。</remarks>
[Conditional("ENABLE_LOG")]
[Conditional("ENABLE_DEBUG_LOG")]
[Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")]
public static void Debug(object message)
{
GameFrameworkLog.Debug(message);
}
// 省略代码...
}
}
注意点
- 静态类(工具类)
- 使用 预处理指令(宏) 与 Conditional特性 设置是否忽略方法调用
- 预处理指令使用 LogScriptingDefineSymbols类 与 ScriptingDefineSymbols类 进行设置
ConditionalAttribute(Conditional特性)
指示编译器,除非定义了指定的有条件编译符号,否则,应忽略方法调用或属性。
参考文档
ConditionalAttribute 类
保留的特性:ConditionalAttribute, ObsoleteAttribute, AttributeUsageAttribute
LogScriptingDefineSymbols
设置Log相关的预处理指令
在Unity编辑器中生成菜单项(让使用者快速设置日志等级)
代码
using UnityEditor;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 日志脚本宏定义。
/// </summary>
public static class LogScriptingDefineSymbols
{
private const string EnableLogScriptingDefineSymbol = "ENABLE_LOG";
private const string EnableDebugAndAboveLogScriptingDefineSymbol = "ENABLE_DEBUG_AND_ABOVE_LOG";
private const string EnableInfoAndAboveLogScriptingDefineSymbol = "ENABLE_INFO_AND_ABOVE_LOG";
private const string EnableWarningAndAboveLogScriptingDefineSymbol = "ENABLE_WARNING_AND_ABOVE_LOG";
private const string EnableErrorAndAboveLogScriptingDefineSymbol = "ENABLE_ERROR_AND_ABOVE_LOG";
private const string EnableFatalAndAboveLogScriptingDefineSymbol = "ENABLE_FATAL_AND_ABOVE_LOG";
private const string EnableDebugLogScriptingDefineSymbol = "ENABLE_DEBUG_LOG";
private const string EnableInfoLogScriptingDefineSymbol = "ENABLE_INFO_LOG";
private const string EnableWarningLogScriptingDefineSymbol = "ENABLE_WARNING_LOG";
private const string EnableErrorLogScriptingDefineSymbol = "ENABLE_ERROR_LOG";
private const string EnableFatalLogScriptingDefineSymbol = "ENABLE_FATAL_LOG";
private static readonly string[] AboveLogScriptingDefineSymbols = new string[]
{
EnableDebugAndAboveLogScriptingDefineSymbol,
EnableInfoAndAboveLogScriptingDefineSymbol,
EnableWarningAndAboveLogScriptingDefineSymbol,
EnableErrorAndAboveLogScriptingDefineSymbol,
EnableFatalAndAboveLogScriptingDefineSymbol
};
private static readonly string[] SpecifyLogScriptingDefineSymbols = new string[]
{
EnableDebugLogScriptingDefineSymbol,
EnableInfoLogScriptingDefineSymbol,
EnableWarningLogScriptingDefineSymbol,
EnableErrorLogScriptingDefineSymbol,
EnableFatalLogScriptingDefineSymbol
};
/// <summary>
/// 禁用所有日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Disable All Logs", false, 30)]
public static void DisableAllLogs()
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(EnableLogScriptingDefineSymbol);
foreach (string specifyLogScriptingDefineSymbol in SpecifyLogScriptingDefineSymbols)
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(specifyLogScriptingDefineSymbol);
}
foreach (string aboveLogScriptingDefineSymbol in AboveLogScriptingDefineSymbols)
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(aboveLogScriptingDefineSymbol);
}
}
/// <summary>
/// 开启所有日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Enable All Logs", false, 31)]
public static void EnableAllLogs()
{
DisableAllLogs();
ScriptingDefineSymbols.AddScriptingDefineSymbol(EnableLogScriptingDefineSymbol);
}
/// <summary>
/// 开启调试及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Enable Debug And Above Logs", false, 32)]
public static void EnableDebugAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableDebugAndAboveLogScriptingDefineSymbol);
}
// 省略代码...
/// <summary>
/// 设置日志脚本宏定义。
/// </summary>
/// <param name="aboveLogScriptingDefineSymbol">要设置的日志脚本宏定义。</param>
public static void SetAboveLogScriptingDefineSymbol(string aboveLogScriptingDefineSymbol)
{
if (string.IsNullOrEmpty(aboveLogScriptingDefineSymbol))
{
return;
}
foreach (string i in AboveLogScriptingDefineSymbols)
{
if (i == aboveLogScriptingDefineSymbol)
{
DisableAllLogs();
ScriptingDefineSymbols.AddScriptingDefineSymbol(aboveLogScriptingDefineSymbol);
return;
}
}
}
}
}
注意点
- 静态类(工具类)
- 使用 MenuItem特性 在Unity编辑器中生成菜单项
- 使用 ScriptingDefineSymbols类 设置 预处理指令
ScriptingDefineSymbols
设置 预处理指令 的工具类
代码
using System.Collections.Generic;
using UnityEditor;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 脚本宏定义。
/// </summary>
public static class ScriptingDefineSymbols
{
private static readonly BuildTargetGroup[] BuildTargetGroups = new BuildTargetGroup[]
{
BuildTargetGroup.Standalone,
BuildTargetGroup.iOS,
BuildTargetGroup.Android,
BuildTargetGroup.WSA,
BuildTargetGroup.WebGL
};
/// <summary>
/// 检查指定平台是否存在指定的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要检查脚本宏定义的平台。</param>
/// <param name="scriptingDefineSymbol">要检查的脚本宏定义。</param>
/// <returns>指定平台是否存在指定的脚本宏定义。</returns>
public static bool HasScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return false;
}
string[] scriptingDefineSymbols = GetScriptingDefineSymbols(buildTargetGroup);
foreach (string i in scriptingDefineSymbols)
{
if (i == scriptingDefineSymbol)
{
return true;
}
}
return false;
}
/// <summary>
/// 为指定平台增加指定的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要增加脚本宏定义的平台。</param>
/// <param name="scriptingDefineSymbol">要增加的脚本宏定义。</param>
public static void AddScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return;
}
if (HasScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol))
{
return;
}
List<string> scriptingDefineSymbols = new List<string>(GetScriptingDefineSymbols(buildTargetGroup))
{
scriptingDefineSymbol
};
SetScriptingDefineSymbols(buildTargetGroup, scriptingDefineSymbols.ToArray());
}
/// <summary>
/// 为指定平台移除指定的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要移除脚本宏定义的平台。</param>
/// <param name="scriptingDefineSymbol">要移除的脚本宏定义。</param>
public static void RemoveScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return;
}
if (!HasScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol))
{
return;
}
List<string> scriptingDefineSymbols = new List<string>(GetScriptingDefineSymbols(buildTargetGroup));
while (scriptingDefineSymbols.Contains(scriptingDefineSymbol))
{
scriptingDefineSymbols.Remove(scriptingDefineSymbol);
}
SetScriptingDefineSymbols(buildTargetGroup, scriptingDefineSymbols.ToArray());
}
/// <summary>
/// 为所有平台增加指定的脚本宏定义。
/// </summary>
/// <param name="scriptingDefineSymbol">要增加的脚本宏定义。</param>
public static void AddScriptingDefineSymbol(string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return;
}
foreach (BuildTargetGroup buildTargetGroup in BuildTargetGroups)
{
AddScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol);
}
}
/// <summary>
/// 为所有平台移除指定的脚本宏定义。
/// </summary>
/// <param name="scriptingDefineSymbol">要移除的脚本宏定义。</param>
public static void RemoveScriptingDefineSymbol(string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return;
}
foreach (BuildTargetGroup buildTargetGroup in BuildTargetGroups)
{
RemoveScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol);
}
}
/// <summary>
/// 获取指定平台的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要获取脚本宏定义的平台。</param>
/// <returns>平台的脚本宏定义。</returns>
public static string[] GetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup)
{
return PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup).Split(';');
}
/// <summary>
/// 设置指定平台的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要设置脚本宏定义的平台。</param>
/// <param name="scriptingDefineSymbols">要设置的脚本宏定义。</param>
public static void SetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup, string[] scriptingDefineSymbols)
{
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, string.Join(";", scriptingDefineSymbols));
}
}
}
注意点
- 静态类(工具类)
- 使用 Unity的PlayerSettings类 设置 预处理指令
PlayerSettings
Player Settings 是您为即将在 Unity 中构建的最终游戏定义各种参数的地方。
其中一些值将用于您打开独立平台游戏时所启动的分辨率对话框。
参考文档
PlayerSettings
Unity中的预处理指令设置
DefaultLogHelper
默认的日志辅助器类
代码
using GameFramework;
using UnityEngine;
namespace UnityGameFramework.Runtime
{
/// <summary>
/// 默认游戏框架日志辅助器。
/// </summary>
public class DefaultLogHelper : GameFrameworkLog.ILogHelper
{
/// <summary>
/// 记录日志。
/// </summary>
/// <param name="level">日志等级。</param>
/// <param name="message">日志内容。</param>
public void Log(GameFrameworkLogLevel level, object message)
{
switch (level)
{
case GameFrameworkLogLevel.Debug:
Debug.Log(Utility.Text.Format("<color=#888888>{0}</color>", message.ToString()));
break;
case GameFrameworkLogLevel.Info:
Debug.Log(message.ToString());
break;
case GameFrameworkLogLevel.Warning:
Debug.LogWarning(message.ToString());
break;
case GameFrameworkLogLevel.Error:
Debug.LogError(message.ToString());
break;
default:
throw new GameFrameworkException(message.ToString());
}
}
}
}
框架类
GameFrameworkLogLevel
框架的日志等级
代码
namespace GameFramework
{
/// <summary>
/// 游戏框架日志等级。
/// </summary>
public enum GameFrameworkLogLevel : byte
{
/// <summary>
/// 调试。
/// </summary>
Debug = 0,
/// <summary>
/// 信息。
/// </summary>
Info,
/// <summary>
/// 警告。
/// </summary>
Warning,
/// <summary>
/// 错误。
/// </summary>
Error,
/// <summary>
/// 严重错误。
/// </summary>
Fatal
}
}
GameFrameworkLog.ILogHelper
日志辅助器接口
namespace GameFramework
{
public static partial class GameFrameworkLog
{
/// <summary>
/// 游戏框架日志辅助器接口。
/// </summary>
public interface ILogHelper
{
/// <summary>
/// 记录日志。
/// </summary>
/// <param name="level">游戏框架日志等级。</param>
/// <param name="message">日志内容。</param>
void Log(GameFrameworkLogLevel level, object message);
}
}
}
注意点
- 该接口处于静态分部类 GameFrameworkLog 的里面
分部类
拆分一个类、一个结构、一个接口或一个方法的定义到两个或更多的文件中是可能的。
每个源文件包含类型或方法定义的一部分,编译应用程序时将把所有部分组合起来。
参考文档
分部类和方法(C# 编程指南)
自定义日志辅助器流程
- 创建一个类并继承该接口(如:MyLogHelper)
- 切换到 Unity编辑器 ,打开 游戏启动场景
- 在从场景下的 BaseComponent(Game Framework/Builtin) 的检视面板中选择 日志辅助器类
GameFrameworkLog
游戏框架日志类
代码
using System.Diagnostics;
namespace GameFramework
{
/// <summary>
/// 游戏框架日志类。
/// </summary>
public static partial class GameFrameworkLog
{
private static ILogHelper s_LogHelper = null;
/// <summary>
/// 设置游戏框架日志辅助器。
/// </summary>
/// <param name="logHelper">要设置的游戏框架日志辅助器。</param>
public static void SetLogHelper(ILogHelper logHelper)
{
s_LogHelper = logHelper;
}
/// <summary>
/// 打印调试级别日志,用于记录调试类日志信息。
/// </summary>
/// <param name="message">日志内容。</param>
/// <remarks>仅在带有 DEBUG 预编译选项时生效。</remarks>
[Conditional("DEBUG")]
public static void Debug(object message)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Debug, message);
}
/// <summary>
/// 打印调试级别日志,用于记录调试类日志信息。
/// </summary>
/// <param name="message">日志内容。</param>
/// <remarks>仅在带有 DEBUG 预编译选项时生效。</remarks>
[Conditional("DEBUG")]
public static void Debug(string message)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Debug, message);
}
/// <summary>
/// 打印调试级别日志,用于记录调试类日志信息。
/// </summary>
/// <param name="format">日志格式。</param>
/// <param name="arg0">日志参数 0。</param>
/// <remarks>仅在带有 DEBUG 预编译选项时生效。</remarks>
[Conditional("DEBUG")]
public static void Debug(string format, object arg0)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg0));
}
/// <summary>
/// 打印调试级别日志,用于记录调试类日志信息。
/// </summary>
/// <param name="format">日志格式。</param>
/// <param name="arg0">日志参数 0。</param>
/// <param name="arg1">日志参数 1。</param>
/// <remarks>仅在带有 DEBUG 预编译选项时生效。</remarks>
[Conditional("DEBUG")]
public static void Debug(string format, object arg0, object arg1)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg0, arg1));
}
/// <summary>
/// 打印调试级别日志,用于记录调试类日志信息。
/// </summary>
/// <param name="format">日志格式。</param>
/// <param name="arg0">日志参数 0。</param>
/// <param name="arg1">日志参数 1。</param>
/// <param name="arg2">日志参数 2。</param>
/// <remarks>仅在带有 DEBUG 预编译选项时生效。</remarks>
[Conditional("DEBUG")]
public static void Debug(string format, object arg0, object arg1, object arg2)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg0, arg1, arg2));
}
/// <summary>
/// 打印调试级别日志,用于记录调试类日志信息。
/// </summary>
/// <param name="format">日志格式。</param>
/// <param name="args">日志参数。</param>
/// <remarks>仅在带有 DEBUG 预编译选项时生效。</remarks>
[Conditional("DEBUG")]
public static void Debug(string format, params object[] args)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, args));
}
/// <summary>
/// 打印信息级别日志,用于记录程序正常运行日志信息。
/// </summary>
/// <param name="message">日志内容</param>
public static void Info(object message)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Info, message);
}
/// <summary>
/// 打印信息级别日志,用于记录程序正常运行日志信息。
/// </summary>
/// <param name="message">日志内容</param>
public static void Info(string message)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Info, message);
}
/// <summary>
/// 打印信息级别日志,用于记录程序正常运行日志信息。
/// </summary>
/// <param name="format">日志格式。</param>
/// <param name="arg0">日志参数 0。</param>
public static void Info(string format, object arg0)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg0));
}
/// <summary>
/// 打印信息级别日志,用于记录程序正常运行日志信息。
/// </summary>
/// <param name="format">日志格式。</param>
/// <param name="arg0">日志参数 0。</param>
/// <param name="arg1">日志参数 1。</param>
public static void Info(string format, object arg0, object arg1)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg0, arg1));
}
/// <summary>
/// 打印信息级别日志,用于记录程序正常运行日志信息。
/// </summary>
/// <param name="format">日志格式。</param>
/// <param name="arg0">日志参数 0。</param>
/// <param name="arg1">日志参数 1。</param>
/// <param name="arg2">日志参数 2。</param>
public static void Info(string format, object arg0, object arg1, object arg2)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg0, arg1, arg2));
}
/// <summary>
/// 打印信息级别日志,用于记录程序正常运行日志信息。
/// </summary>
/// <param name="format">日志格式。</param>
/// <param name="args">日志参数。</param>
public static void Info(string format, params object[] args)
{
if (s_LogHelper == null)
{
return;
}
s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, args));
}
// 省略代码...
}
}
注意点
- 静态分部类
- 使用 ILogHelper接口 记录日志
- 在游戏启动时,BaseComponent组件(Unity脚本) 会调用 SetLogHelper方法 设置日志辅助器。
- 应该是 策略模式 吧
类图
Log
GameFrameworkLog