做Unity3d开发,Debug输出打印是我日常打交道最多的功能之一,夸张点说,不比碰编辑器的次数少。很多新手搜“debug怎么用”,上来就只知道Debug.Log,遇到问题就打一条日志,然后盯着Console发呆。Unity的调试输出远不止“打一句话看看”这么简单,它包含分级日志、可视化绘制、条件编译裁剪、真机远程日志等一系列手段,用好了能大幅缩短排查时间,用不好反而会成为性能隐患和线上事故的导火索。
这篇内容我按实际项目里最常用的几条线来写:先讲Debug.Log家族的正确用法,再讲DrawLine这类可视化输出,然后是自建日志系统的设计和性能考量,最后是真机调试和发布版本的处理。适合刚接触Unity的初学者,也适合已经写了几年业务代码但没系统整理过调试方案的人。我会把实际项目中踩过的坑一并写出来。
1. 从Debug.Log说起:Unity调试输出的三条主通道
1.1 Log、Warning、Error分级到底怎么用
Unity的Debug类里最基础的就是三个输出方法:Debug.Log、Debug.LogWarning、Debug.LogError。它们对应Console面板里的三种图标,也对应LoggerType里的Info、Warning、Error三个级别。很多项目对这三级的使用是混乱的——有人把普通状态全用Debug.Log,有人把所有问题都打成Error,结果就是Console里一片红,真正严重的问题反而被淹没。
我的建议很简单:Log用来记录关键流程节点和变量值,比如进入某个状态、加载完成、按钮被点击;Warning用来标记“可能导致问题但不影响当前运行”的情况,比如配置缺失、使用了过时的接口、某个返回值超出了预期范围;Error用来标记“如果不处理就会产生错误结果”的异常分支,比如空引用、加载失败、状态机进入非法状态。分级不是为了好看,是为了以后过滤日志时能快速定位级别对应的问题。
实际操作时还有一个细节:Debug.LogError并不会中断游戏执行,它只是标记一条错误日志。如果你希望出错时暂停编辑器便于现场排查,可以在Console面板里打开Error Pause(或者用快捷键,默认是Shift+Ctrl+C的开关),也可以调用Debug.Break()。但要注意Debug.Break()在真机上无效,它只在编辑器里生效,真机调试时别指望用它中断。
1.2 日志格式里的隐形信息:调用堆栈与日志标签
Console里每条日志默认会显示调用堆栈,双击日志可以跳到对应的代码行,这是定位问题最直接的手段。但堆栈信息不是免费的。在开发版本里,每条Debug.Log都会抓取并保存堆栈信息,频繁调用时GC分配相当可观。这个后面性能部分我会展开说,这里先记住一个设置:Player Settings的StackTrace选项,默认是EngineOnly或Full,如果你只在编辑器里看日志,建议把Managed部分的堆栈选为None,能减少真机上的性能损耗。
日志标签也是容易被忽略的点。Debug.Log的第一个参数直接拼字符串,有时候在几十几百条日志里找一条目标日志非常痛苦。我习惯在关键模块前加固定前缀,比如“[ResLoader]”“[UI]”“[Network]”,这样在Console的搜索框里直接过滤前缀就能锁模块。Unity的Console搜索支持模糊匹配,输入[Network]就能过滤出网络模块所有日志,比单纯靠肉眼扫有效得多。
如果想让日志在Console里高亮,可以用富文本标签,比如Debug.Log("<color=#66CCFF>[ResLoader]</color> 加载图片: " + url)。Console里颜色能正常显示,这在区分多个模块同时输出时非常有用。真机上Unity日志系统也支持这个标签,Android Logcat里会显示对应的ANSI颜色,不过大部分情况下真机上颜色没什么意义,主要是编辑器里提高辨识度。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 可视化调试:DrawLine、DrawRay 与 OnDrawGizmos 的分工
2.1 Debug.DrawLine 与 Debug.DrawRay 的适用场景
日志只能输出数字和文本,但很多问题本质上是空间问题:AI为什么走到了那个位置、攻击判定范围到底有多大、两个物体的相对朝向对不对
