日志不是上线后才补的功能
个人游戏开发时,很多问题靠编辑器控制台和断点就能解决。但 Steam 上线后,玩家不会带着编辑器运行,也不会知道哪些截图对你有用。他们能提供的通常是一句话:“打开黑屏”“第二章读档卡住”“打完 Boss 后退不出去”。如果游戏没有版本号、日志、崩溃文件和反馈入口,这些信息很难变成可执行任务。
日志系统的目标不是记录一切,而是在出问题时回答几个问题:玩家运行的是哪个构建,进入了哪个场景,加载了哪些关键资源,存档版本是什么,Steam API 是否初始化成功,崩溃前最后一个稳定状态在哪里。个人项目不需要复杂后台,但至少要在本地生成可读文件,并让玩家知道如何找到它。
先定义日志分级
日志分级可以保持简单:
| 级别 | 用途 | 是否写入发行日志 |
|---|---|---|
| Debug | 开发期细节,如 AI 决策、碰撞检测 | 默认关闭 |
| Info | 关键流程,如启动、读档、切场景 | 写入 |
| Warn | 可恢复异常,如资源缺失备用、配置回退 | 写入 |
| Error | 功能失败,如存档写入失败、Steam 初始化失败 | 写入 |
| Fatal | 崩溃或无法继续 | 写入并尽量生成崩溃文件 |
不要在发行版里每帧写 Debug,也不要把所有异常都吞掉。日志过多会影响性能,日志过少又无法定位。比较实用的做法是默认记录 Info 以上,玩家遇到问题时可通过启动参数或设置打开详细日志。
每次启动先写环境信息
日志开头应该固定写一段环境信息:
| 字段 | 示例 |
|---|---|
| 游戏版本 | 1.0.0-rc2 |
| 构建编号 | 2021.04.02-win-full-01 |
| Git 提交 | a1b2c3d |
| 平台 | Windows x64 |
| Steam 启动 | true |
| 语言 | zh-CN |
| 分辨率 | 1920x1080 |
| 存档版本 | 4 |
这些字段会让玩家反馈立刻有上下文。尤其是构建编号和 Steam 启动状态,能快速判断玩家是否下载到新补丁、是否绕过 Steam 直接运行、是否仍在旧分支。
关键路径要留痕
不是所有函数都要写日志,但关键路径必须留痕:
- 启动流程:配置读取、Steam API 初始化、语言选择。
- 资源加载:主资源包、关卡包、字体、音频。
- 存档流程:发现槽位、加载版本、迁移结果、写入结果。
- 场景切换:从哪里到哪里,耗时多久。
- Steam 功能:成就、云存档、覆盖层、分支识别。
- 异常恢复:备用资源、默认设置、备份存档。
写日志时要带状态,不要只写“加载完成”。更有用的是“加载 chapter_02,耗时 3.4 秒,资源包版本 12”。这样看到卡顿或失败时,才能和版本、场景、资源对应。
崩溃报告的最低配置
个人项目即使不接入第三方崩溃平台,也应该保存崩溃文件。最低要求:
| 内容 | 说明 |
|---|---|
| 崩溃时间 | 用本地时间和 UTC 都可以,保持一致 |
| 游戏版本 | 对应构建编号 |
| 堆栈或错误类型 | 引擎能提供多少写多少 |
| 最近日志片段 | 崩溃前 100 到 300 行 |
| 存档槽信息 | 不写敏感内容,只写槽位和版本 |
| 系统信息 | 操作系统、显卡、内存概况 |
崩溃文件不要包含玩家隐私、完整用户名、绝对路径中的个人目录、聊天文本或账号信息。日志有用,但隐私边界也要清楚。
玩家如何提交日志
不要指望玩家自己知道日志在哪里。游戏内设置页、Steam 讨论区置顶帖、补丁公告里都可以写清楚:
- 打开游戏设置。
- 点击“打开日志目录”。
- 复制
latest.log和crash_日期.log。 - 在反馈表或邮箱中附上复现步骤。
如果游戏无法启动,就在 Steam 讨论区提供路径说明。路径要分 Windows、macOS、Linux 写清楚。不要只写“在 AppData 里”,很多玩家不会找。
复现步骤模板
玩家反馈要转成缺陷,模板很关键:
| 问题 | 示例 |
|---|---|
| 发生位置 | 第二章工厂门口 |
| 发生前做了什么 | 读取自动存档后立刻打开背包 |
| 是否每次发生 | 三次中两次 |
| 使用设备 | 键鼠,Windows 10 |
| 游戏版本 | 主菜单右下角 1.0.0-rc2 |
| 附件 | 日志、截图、存档 |
反馈模板越具体,玩家越容易提供有用信息。个人开发者时间少,不能在十几轮追问中拼凑线索。
日志和性能的平衡
日志系统本身不能制造卡顿。常见错误包括:每帧写文件、战斗中大量拼接字符串、同步写入大文件、日志无限增长。发行版可以使用环形缓冲或按大小滚动,比如保留最近 3 个日志文件,每个 2MB 到 5MB。
对高频事件,只记录状态变化,不记录每帧状态。比如不要每帧写“敌人正在追踪玩家”,而是在敌人进入追踪、失去目标、攻击、死亡时记录。这样既能定位流程,又不会污染日志。
调试开关和启动参数
给发行版保留几个受控开关很有用:
| 开关 | 用途 |
|---|---|
--verbose-log | 打开详细日志 |
--safe-mode | 使用默认画质和窗口模式启动 |
--no-controller | 排查手柄输入问题 |
--reset-config | 重建本地配置 |
--log-folder | 打开或指定日志目录 |
这些参数可以写在支持文档里。玩家遇到黑屏时,safe-mode 往往比让他手动删配置更稳。注意不要把跳关、解锁全部成就、测试商店之类的内部参数留给玩家使用。
发布后排错流程
收到玩家反馈后,可以按这个顺序处理:
- 看版本号,确认是否为当前构建。
- 看启动方式,确认是否从 Steam 客户端启动。
- 看最后一个稳定日志点。
- 对照存档版本和场景。
- 询问最少的补充信息。
- 本地复现或制作诊断构建。
- 修复后在相同路径回归。
- 在补丁说明里写清影响范围。
不要一看到崩溃就盲改。没有定位的修复很容易引入新问题。
最终检查清单
- 发行版日志默认记录 Info 以上。
- 日志开头包含版本、构建、平台和 Steam 启动状态。
- 关键路径有明确状态和耗时。
- 崩溃文件包含最近日志和基础环境。
- 日志不写敏感信息。
- 玩家能在文档中找到提交日志方式。
- 详细日志和安全模式可通过受控开关启用。
- 每次补丁后验证日志仍能生成。
日志系统做得好,发布后很多问题会从“玩家说坏了”变成“某构建在某场景读档后资源包缺失”。这就是个人开发者能快速修补 Steam 版本的基础。
日志文件的位置和生命周期
日志目录要固定,并且不要写到游戏安装目录。Windows 可以放在用户 AppData,macOS 放在 Application Support,Linux 放在 XDG 对应目录。路径选择要和存档、设置分开,避免玩家清理日志时误删进度。
日志生命周期也要设计。比较实用的方式是每次启动生成 latest.log,上一份移动为 previous.log,崩溃时额外写 crash_日期.log。如果长期运行,可以按大小滚动,避免日志占用磁盘。
| 文件 | 用途 |
|---|---|
latest.log | 当前运行记录 |
previous.log | 上一次运行记录 |
crash_*.log | 崩溃相关记录 |
diagnostic.txt | 玩家主动导出的环境信息 |
玩家反馈时通常只需要最新日志和崩溃日志。文件越清楚,支持沟通越省力。
日志中的可复现标记
为了让反馈更容易复现,可以在日志里记录随机种子、关卡 ID、难度、输入设备和当前分支。尤其是随机生成关卡或掉落的游戏,如果没有 seed,很难复现玩家遇到的组合。
例如一行日志可以包含:
run_start build=2021.04.02-win-full-01 level=forest_03 seed=842193 difficulty=normal input=controller
这类结构化日志比自然语言更容易搜索。即使用普通文本,也要保持字段一致。后续你可以用 rg 快速找到所有 save_failed、steam_init_failed 或某个关卡的异常。
诊断构建的使用
有些问题在普通发行版日志里不够详细,可以给受影响玩家提供诊断构建或诊断启动参数。诊断构建应只增加日志和安全检查,不要加入未验证的新逻辑。否则你无法判断问题是原来的 bug,还是诊断构建带来的变化。
诊断构建也要有过期策略。问题解决后,不要让玩家长期停留在诊断分支。Steam 分支说明里写清用途、密码和预计关闭时间,避免未来有人下载到旧测试包。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。