3、日志系统入门:Debug.Log、打印技巧、日志分级、日志文件管理
日志系统,说白了就是游戏运行时的「黑匣子」。
你想想看,游戏跑起来之后,我们看不到内部状态。变量对不对?逻辑走没走?报错在哪?全靠日志告诉我们。我个人习惯,写代码之前先把日志想好——这不是小题大做,是血的教训换来的。
3.1 Debug.Log:最基础的打印
Unity 里最常用的就是 Debug.Log()。用法很简单:
Debug.Log("玩家进入关卡");
Debug.Log("当前血量:" + hp);
Debug.Log($"坐标:{transform.position}"); // C# 字符串插值
嗯,这里要注意:字符串拼接在频繁调用时会有性能开销。我在项目中遇到过,某个战斗系统每帧打印几十条日志,结果手机发烫严重。后来全改成条件编译才解决。
小技巧:用
Debug.LogFormat() 或字符串插值,比用 + 拼接更优雅,性能也稍好。
3.2 打印技巧:别只会用 Log
Unity 其实给了我们三种打印方法:
| 方法 | 用途 | 编辑器颜色 |
|---|---|---|
Debug.Log() |
普通信息 | 白色 |
Debug.Warning() |
警告信息 | 黄色 |
Debug.Error() |
错误信息 | 红色 |
为什么要区分?因为扫日志的时候,黄色和红色能让你一眼定位问题。我曾经接手过一个项目,全用 Debug.Log(),几万行日志混在一起,找错误像大海捞针。
还有一个实用技巧:打印对象引用。
Debug.Log("敌人死亡", enemyObj);
这样在 Console 窗口点击日志,会自动高亮对应的游戏对象。调试时特别方便,省得你满场景找物体。
核心原则:日志要让人「一眼看懂」——谁、在哪、发生了什么。
3.3 日志分级:别让日志刷屏
游戏开发中,日志量是惊人的。如果不分级,你会发现 Console 窗口刷得飞起,真正有用的信息反而被淹没了。
我一般把日志分成四个级别:
- Error(错误):游戏崩溃、资源加载失败、关键逻辑异常。必须修复。
- Warning(警告):可能有问题但不致命,比如配置缺失、性能警告。
- Info(信息):正常流程记录,比如玩家进入场景、任务完成。
- Debug(调试):开发阶段用的细粒度日志,发布时应该关掉。
怎么实现分级?我习惯写一个简单的日志管理器:
public enum LogLevel
{
Debug,
Info,
Warning,
Error
}
public static class Logger
{
public static LogLevel CurrentLevel = LogLevel.Debug;
public static void Log(LogLevel level, string message)
{
if (level < CurrentLevel) return;
switch (level)
{
case LogLevel.Debug:
Debug.Log("[DEBUG] " + message);
break;
case LogLevel.Info:
Debug.Log("[INFO] " + message);
break;
case LogLevel.Warning:
Debug.LogWarning("[WARN] " + message);
break;
case LogLevel.Error:
Debug.LogError("[ERROR] " + message);
break;
}
}
}
使用时:
Logger.Log(LogLevel.Info, "玩家进入关卡");
Logger.Log(LogLevel.Debug, "怪物AI状态切换"); // 发布时关掉
注意:发布版本一定要把 Debug 级别的日志关掉。我曾经有个项目,Debug 日志里不小心打印了完整的玩家数据,结果被玩家抓包反编译……嗯,很尴尬。
3.4 日志文件管理:让日志「可追溯」
编辑器里看日志很方便,但游戏发布到玩家手机上怎么办?这时候就需要日志文件了。
我常用的方案:
- 写入本地文件:用
Application.persistentDataPath作为路径 - 按日期分文件:每天一个日志文件,方便查找
- 限制文件大小:超过 10MB 自动滚动,防止撑爆存储
一个简单的文件日志实现:
using System.IO;
using System.Text;
public class FileLogger
{
private static string logPath;
private static StringBuilder sb = new StringBuilder();
public static void Init()
{
logPath = Application.persistentDataPath + "/logs/";
if (!Directory.Exists(logPath))
Directory.CreateDirectory(logPath);
}
public static void Write(string message)
{
string fileName = "log_" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
string fullPath = logPath + fileName;
sb.Clear();
sb.Append("[");
sb.Append(DateTime.Now.ToString("HH:mm:ss"));
sb.Append("] ");
sb.AppendLine(message);
File.AppendAllText(fullPath, sb.ToString());
}
}
调用时:
FileLogger.Write("玩家登录,ID: 10086");
进阶建议:加上「日志上传」功能。玩家遇到 bug 时,一键上传日志文件到服务器,能极大提升排查效率。我在项目中就靠这个功能,远程定位了好几个诡异的闪退问题。
3.5 避坑指南
最后分享几个我踩过的坑:
- 不要在 Update 里打日志——每帧打印,手机瞬间变暖手宝
- 日志里不要放敏感信息——玩家账号、设备 ID 等,容易被抓包
- 日志文件记得加密或混淆——防止玩家恶意篡改
- 发布前检查所有 Debug.Log——我习惯用宏控制,发布版本自动移除
日志系统看似简单,但用好了能省下大量调试时间。记住一句话:好的日志,是写给未来自己的信。