
2024 年之后独立游戏开发者最关心的一个问题不再是“我不会画画怎么办”而是“我一个人能不能在合理时间内做完一款能上架的游戏”。放置类游戏《细菌克星》就是在这个背景下诞生的项目它由一个人完成主要开发AI 承担了大量代码生成、素材创作和文案整理工作最终通过了 Steam 平台的审核并正式上线。这篇文章会把整个开发链路拆开讲清楚包括玩法设计、技术选型、核心系统实现、Steamworks 接入、商店页上架以及上线前后真正容易踩的坑。我的判断很直接AI 不会让一个没有想法的策划做出好游戏但它能让一个已经有玩法想法的人用过去三分之一的时间把想法变成 Steam 上的真实产品。放置类游戏尤其适合这件事因为它的系统边界清晰、玩法闭环简单、数值驱动明确几乎是为 AI 辅助开发量身定制的品类。这篇文章对于三类读者最有价值打算做第一款独立游戏但担心工程量的人已经在用 AI 写业务代码、想尝试游戏开发的后端或前端工程师以及已经做完玩法原型、但卡在 Steam 上架流程的独立开发者。读完你可以得到一条从零到上线可复用的路线以及哪些环节必须自己守、哪些环节可以放心交给 AI 的具体边界。1. 放置类游戏单人开发者最适合切入的品类放置类游戏Idle Game / Incremental Game的核心特征是玩家只需要极少量的操作游戏就会自动产出资源。最有代表性的例子是浏览器起家的 Cookie Clicker玩家不断点击一块饼干获取数字再用数字购买自动产出设施关闭页面后回来还能领取离线收益。这类游戏的玩法深度不在操作上而在数值成长的节奏上。从开发角度看放置类游戏有三个对其他品类不一定成立的优势第一玩法系统闭环。放置游戏不需要复杂的三维场景、物理碰撞、AI 敌人或者多人同步核心只需要“资源产出—资源消耗—成长升级”这一个循环。这意味着玩法的核心逻辑可以用很小的代码量先跑通整个项目不会在早期失控。第二工程边界清晰。存档、UI、数值、成就、离线收益每个模块都相对独立。对于 AI 辅助开发来说模块边界越清晰AI 生成的代码越不容易互相污染人工审查的难度也越低。如果做一个开放世界 RPGAI 生成的代码分散在上百个文件里出了问题很难定位但放置游戏的核心逻辑可能只有十几个脚本AI 生成的每一段代码都能很快被验证。第三留存验证成本低。放置游戏的乐趣来自“数字变大的快感”所以验证一个版本是否好玩不需要邀请大量玩家做复杂的问卷调查只需要观察两个指标玩家愿意挂机多久愿意点多少次。这非常符合单人开发者的验证能力。《细菌克星》选择的是“消灭细菌、净化实验室”的主题。玩家扮演一名实验室消毒专家通过点击消灭培养皿里的细菌获得净化值再用净化值购买紫外线灯、自动消毒机器人等升级设施。游戏的循环是点击杀菌获得净化值净化值购买自动设施自动设施提高单位时间产出离线后回来领取离线收益解锁新的细菌图鉴和成就。这个主题的好处是世界观简单美术可以用扁平化风格承载而且“细菌繁殖”和“数字膨胀”在直觉上是匹配的——你会觉得细菌越变越多是合理的净化值越变越大也是合理的。2. 《细菌克星》的核心玩法与系统拆解正式编码之前先把游戏拆成六个核心系统每一个做完之后都能独立验证。第一个是点击系统。玩家点击画布上的细菌立即获得一次净化值。点击产出由基础值和点击等级加成决定公式很简单BaseClickOutput clickLevel * 0.2。点击系统是游戏的第一层反馈它必须足够“爽”所以每次点击要考虑轻微动画、数字飘字和音效这些效果可以用 Unity 的 UI 动画和 AudioSource 快速实现。第二个是自动产出系统。当玩家拥有自动消毒设备后设备每隔一秒钟产生一次净化值。自动产出是所有放置游戏的“发动机”它的数值成长决定了游戏的节奏。这里我采用了经典的指数增长公式BaseAutoOutput * AutoGrowth^autoLevel其中 AutoGrowth 是 1.15。前期增长速度平缓后期升级成本越来越高玩家就需要在“点击加速”和“等待自动产出”之间做选择。第三个是升级系统。升级项可以拆成两类一类是点击增强一类是自动产出增强。每次升级都会增加净化值消耗消耗公式也需要和产出公式匹配否则游戏会在某个数值区间突然变得无法推进。这里真正容易踩坑的地方是数值曲线不收敛产出是指数上涨但升级成本是线性上涨那么后期玩家会无限膨胀反过来升级成本涨得太快玩家会在第 20 级左右就彻底失去动力。比较稳妥的做法是先让 AI 生成一组候选数值表再用一个简单的模拟脚本跑 50 个小时的挂机曲线观察瓶颈出现在哪一级再人工调整权重。第四个是离线收益系统。玩家关闭游戏一段时间后再打开时按时间差补发一部分净化值。离线收益需要设置上限否则玩家离开一个月回来直接满级游戏生命周期就崩了。《细菌克星》的离线收益上限是 8 小时超过部分按 8 小时计算。这个上限值放在常量类里方便后续根据玩家反馈调整。第五个是图鉴和成就系统。图鉴用来收集不同种类的细菌每解锁一种细菌就获得属性加成成就是用来自我驱动玩家完成特定目标比如“累计点击 1000 次”“拥有 10 台自动消毒设备”。放置类游戏的留存核心就是目标感没有成就系统的话玩家会在数字增长变慢的第一时间流失。第六个是存档系统。存档负责保存玩家当前净化值、累计产出、点击等级、自动产出等级和上次保存时间。存档使用 JSON 序列化本地用 PlayerPrefs 保存。存档系统虽然看起来简单但它是上线后事故率最高的模块之一后面会专门讲。六个系统的关系是单向依赖点击系统和自动产出系统产生净化值净化值驱动升级系统升级系统反向强化产出离线收益在玩家回归时补发产出图鉴和成就提供长期目标存档把这一切的状态持久化。单依赖关系让 AI 生成的代码非常容易拆分和审查。3. 技术选型与环境准备《细菌克星》的客户端选择了 Unity 加 C#。原因是放置类游戏大量依赖 UI 交互和定时器Unity 的 UGUI 和 MonoBehaviour 生命周期天然适合这种玩法同时 Unity 对 Steamworks 的支持非常成熟无论是官方的 Steamworks.NET 还是社区方案都能在几个小时内接入完成。你完全可以用 Godot 或者纯 Web 实现放置游戏但从“后续要上 Steam、要接成就、要云存档”这个目标回溯Unity 的项目资料和插件生态是最省事的。开发环境建议如下操作系统Windows 10 或 Windows 11打包 Windows 客户端最方便。Unity推荐使用 LTS 版本项目版本以实际工程为准。放置游戏没有特别依赖新版本渲染特性的地方稳定优先。IDEVisual Studio 或 JetBrains Rider 均可关键是能配合 AI 插件做代码补全。版本控制Git 加 Git LFS。Unity 工程的场景文件、贴图资源比较大必须启用 LFS 避免仓库体积失控。Steam 开发者账号在 Steamworks 官网注册开发者账号并完成实名验证然后创建应用获得 AppID。Steamworks SDK从 Steamworks 下载站获取对应 SDKUnity 项目建议直接通过包管理安装 Steamworks.NET。AI 工具一个用于对话式编写代码的大语言模型一个 IDE 内的代码补全插件还有一个用于生成 2D 素材的文生图工具。具体工具版本不重要重要的是建立自己的工作流。环境准备这一步最容易犯的错误是希望把环境一次配到完美再动手。实际经验是先装 Unity 和 Git跑通一个最简单的场景再逐步加 Steamworks。不要在第一天就接 AI 插件、配 CI、搭云存档这些都会变成拖延上线的借口。4. 用 AI 搭建开发工作流AI 辅助开发不是“把需求丢给 AI然后等一个完整游戏”而是把开发过程拆成三个可重复的工作流。第一个工作流是需求对话式编码。给 AI 描述清楚模块需求要求它输出完整脚本而不是片段。关键是提示词里要包含输入、输出、边界条件和文件路径。以离线收益计算器为例可以这样写你是一名经验丰富的 Unity C# 开发者。请为放置类游戏编写一个离线收益计算器。 要求 1. 提供静态方法 Calculate(GameData data, DateTime lastSaveTime, DateTime now)。 2. 离线超过 8 小时按 8 小时计算。 3. 产出公式为离线秒数 * BaseAutoOutput * 1.15^autoLevel。 4. 返回 double 类型。 5. 如果 lastSaveTime 大于等于 now返回 0。 6. 请给出一段可直接放入 Unity 工程的代码并给出三个边界测试用例。这个提示词包含了 AI 需要知道的所有关键信息。如果你的问题描述含糊AI 就会给出一个看起来正确但无法直接编译的通用模板。让 AI 生成代码时永远要求它给出可运行的完整文件而不是高亮的核心片段因为你还需要审查它。第二个工作流是报错修复闭环。Unity 的编译报错、运行时报错直接把日志复制给 AI附带上对应的脚本文件和操作步骤。例如“点击按钮后净化值没有变化控制台也没有报错”AI 通常会先建议你检查 UI 事件绑定和数据引用。这个闭环能省下大量搜索时间。但要记住AI 给出的修复建议是基于概率的不是基于你项目里真实状态的所以每一条修复都必须自己验证。第三个工作流是素材与文案生产。细菌图标、按钮背景、UI 装饰这类 2D 素材可以用文生图模型生成初稿再在像素级做人工整理和重绘。需要特别注意的是Steam 商店页面对 AI 生成内容有披露要求所以团队需要在项目文档里记录哪些素材使用了 AI 生成使用的工具和生成参数是什么避免审核环节被要求补充说明时无从下手。还有一条贯穿始终的原则AI 输出的所有东西都是草案不是最终交付物。代码要逐行审查美术要人工重绘关键部分文案要对着 Steam 审核规范核对一遍。AI 负责把“从 0 到 1”的时间缩短人工负责把“从 1 到能上线”的质量补齐。5. 核心系统实现放置循环、离线收益与存档下面给出《细菌克星》中三个最核心的模块代码文件路径和逻辑说明都已经标注好可以直接放到 Unity 工程中跑通。首先是常量类集中管理所有数值曲线参数。// 文件路径Assets/Scripts/Core/GameConstants.cs namespace BacteriaKiller.Core { public static class GameConstants { // 点击基础产出 public const double BaseClickOutput 1.0; // 自动净化设备的基础产出 public const double BaseAutoOutput 0.5; // 自动产出的成长倍率 public const double AutoGrowth 1.15; // 离线收益上限单位小时 public const int MaxOfflineHours 8; } }然后是数据模型。注意净化值这类长期数值使用 double 而不是 int因为放置游戏运行一段时间后数值会非常大int 会迅速溢出。// 文件路径Assets/Scripts/Models/GameData.cs using System; namespace BacteriaKiller.Models { [Serializable] public class GameData { public double purifyValue; // 当前净化值 public double totalEarned; // 累计获得净化值 public int clickLevel; // 点击升级等级 public int autoLevel; // 自动净化等级 public string saveTime; // 上次保存时间 } }核心管理器负责点击产出和自动产出。这里使用累加器控制自动产出节奏而不是每帧都增加产出这样即使是 144Hz 的显示器也不会导致产出速度异常。// 文件路径Assets/Scripts/Core/BacteriaManager.cs using System; using BacteriaKiller.Models; using UnityEngine; namespace BacteriaKiller.Core { public class BacteriaManager : MonoBehaviour { public GameData data new GameData(); private float _accumulator; public void OnClickBacteria() { double output GetClickOutput(); data.purifyValue output; data.totalEarned output; } private void Update() { _accumulator Time.deltaTime; if (_accumulator 1f) { _accumulator - 1f; AddAutoOutput(); } } private void AddAutoOutput() { double output GetAutoOutput(); data.purifyValue output; data.totalEarned output; } public double GetClickOutput() { return GameConstants.BaseClickOutput data.clickLevel * 0.2; } public double GetAutoOutput() { return GameConstants.BaseAutoOutput * Math.Pow(GameConstants.AutoGrowth, data.autoLevel); } } }这里面真正容易出错的地方是 Math.Pow。在 Unity 中新手容易写成 Mathf.Pow但 Mathf.Pow 的参数和返回值是 float指数增长几十级后精度损失会非常明显大数值会出现跳动。放置游戏的数值系统必须使用 System.Math这一点 AI 生成的代码有时会忽略人工审查时一定要盯住。接下来是离线收益计算器。它和 BacteriaManager 共用 GameConstants保证产出公式的一致性。// 文件路径Assets/Scripts/Core/OfflineRewardCalculator.cs using System; using BacteriaKiller.Models; namespace BacteriaKiller.Core { public static class OfflineRewardCalculator { public static double Calculate( GameData data, DateTime lastSaveTime, DateTime now) { if (lastSaveTime now) { return 0; } TimeSpan offline now - lastSaveTime; double maxSeconds TimeSpan.FromHours(GameConstants.MaxOfflineHours).TotalSeconds; if (offline.TotalSeconds maxSeconds) { offline TimeSpan.FromSeconds(maxSeconds); } double baseOutput GameConstants.BaseAutoOutput * Math.Pow(GameConstants.AutoGrowth, data.autoLevel); return offline.TotalSeconds * baseOutput; } } }最后是存档管理。存档时间以字符串形式保存读取时先检查 PlayerPrefs 中是否存在键避免首次运行时报空引用。// 文件路径Assets/Scripts/Core/SaveManager.cs using System; using BacteriaKiller.Models; using UnityEngine; namespace BacteriaKiller.Core { public static class SaveManager { private const string SaveKey BacteriaKiller_SaveData; public static void Save(GameData data) { data.saveTime DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss); string json JsonUtility.ToJson(data); PlayerPrefs.SetString(SaveKey, json); PlayerPrefs.Save(); } public static GameData Load() { if (!PlayerPrefs.HasKey(SaveKey)) { return new GameData(); } string json PlayerPrefs.GetString(SaveKey); GameData data JsonUtility.FromJsonGameData(json); if (data null) { return new GameData(); } return data; } } }用 Unity 跑通这组代码的验证步骤很简单新建一个空场景创建一个 GameObject 挂上 BacteriaManager再创建一个按钮按钮的 OnClick 事件绑定到 BacteriaManager 的 OnClickBacteria 方法。运行后点击按钮看到净化值增长等待一秒看到自动产出生效手动调用一次 SaveManager.Save 和 Load确认存档能正确恢复。这一步跑通了放置游戏的核心循环就成立了一半。6. Steamworks SDK 接入与商店页上架游戏本地逻辑跑通之后下一步是接入 Steamworks 并准备上架。过程可以拆成三个部分开发者账号与 AppID、Steam 客户端接入、商店页面和构建上传。Steamworks 开发者在官网完成注册后需要创建应用并等待 Valve 审核。拿到 AppID 之后Unity 工程中需要把 AppID 写入steam_appid.txt文件否则在编辑器和本地构建里调用 SteamAPI.Init 会失败。这个文件通常放在 Assets 根目录或构建输出目录具体位置以 SDK 文档为准。Unity 集成 Steam 推荐使用 Steamworks.NET 包。接入的核心代码只有一个初始化管理类// 文件路径Assets/Scripts/Steam/SteamManager.cs using Steamworks; using UnityEngine; namespace BacteriaKiller.Steam { public class SteamManager : MonoBehaviour { private void Awake() { if (!SteamAPI.Init()) { Debug.LogError(SteamAPI 初始化失败请检查本地是否已启动 Steam 客户端); } } private void OnDestroy() { SteamAPI.Shutdown(); } } }这段代码放在一个常驻 GameObject 上游戏启动时先初始化 Steam销毁时正常关闭。注意 SteamAPI.Init 的成功依赖两个条件Steam 客户端在运行以及 AppID 配置正确。如果调试时失败优先检查这两个条件而不是代码本身。上架流程中第二重要的是构建和上传。Steam 使用 Depot 的概念来管理构建内容你需要为游戏创建一个包含完整构建文件的 Depot配置 Depot 路径然后通过 SteamPipe 命令行工具上传。上传过程本质上是把本地构建目录和 Steam 的 Depot 建立映射第一次配置稍繁琐之后每次更新都是重复相同操作。这里要特别提醒上传前一定要在本地用“仅限自己可见”的途径测试一次完整构建确认从 Steam 客户端启动游戏后存档、Steam 初始化、音频都正常再考虑公开。商店页面是上架的关键门槛。需要准备的素材包括横版宣传图、竖版宣传图、最少 5 张截图、一段宣传视频、游戏简介、标签分类和价格设定。文案部分可以用 AI 生成初稿但必须人工核对因为 Steam 对游戏描述的审核比较严格不能出现虚假宣传或误导性内容。如果素材中含有 AI 生成内容上传审核时需按平台要求如实披露。7. 上线前后常见问题与排查思路开发和上线过程中《细菌克星》遇到过的典型问题整理成一张表按现象、原因、排查方式和解决方案四列列出。这些问题在放置类游戏里非常普遍可以直接复用排查思路。问题现象可能原因排查方式解决方案点击按钮后净化值不变UI 事件未绑定或按钮引用了错误的 GameData 实例检查 Inspector 中 OnClick 绑定以及 GameData 是单例还是 new 出来的临时对象使用统一管理器持有 GameData按钮事件只绑定管理器方法自动产出不增加Time.timeScale 被暂停逻辑改为 0或累加器逻辑异常查看日志确认 Update 是否执行检查暂停代码产出逻辑不要依赖 timeScale改用独立计时离线收益为 0saveTime 字符串解析失败或玩家上次存档时间异常打印 DateTime.Parse 的结果解析失败时返回 0并统一时间格式增加异常保护存档丢失PlayerPrefs 被清除或云存档覆盖了本地新存档查看保存键名、平台差异和云存档同步日志接入 Steam 云存档时使用独立文件名保留一份本地上一次备份SteamAPI 初始化失败本地未启动 Steam或 steam_appid.txt 缺失确认 Steam 进程和 AppID 配置按 SDK 要求放置 steam_appid.txt教程环境先通过 Steam 启动大数字显示混乱double 数值过大时直接 ToString出现科学计数法检查 UI 文本是否直接绑定原始数值实现单位缩写格式化例如 1.2K、3.4M、5.1B商店审核要求补充 AI 内容说明商店截图或描述中的素材由 AI 生成查看 Steam 审核消息要求如实披露 AI 生成素材保留生成记录必要时人工重绘关键素材这里最影响上线进度的是商店审核。审核消息一般会明确告诉你缺什么按要求补齐即可不需要过度担心。但从实际经验看最容易拖慢进度的反而是本地构建问题你本地运行正常打包出来后存档路径变化、Steam 初始化失败、字体丢失这类问题必须提前按照“从 Steam 客户端启动构建”的方式测一遍。8. AI 辅助开发的边界与实战建议AI 在《细菌克星》开发中承担了大量工作但它的边界非常清楚。可以放心交给 AI 的任务包括样板代码生成、模块脚手架、报错日志分析、单元测试用例编写、商店页面文案初稿、数值表格初稿、素材初稿。不能交给 AI 的任务包括核心玩法决策、数值平衡的最终调整、Steam 审核合规、玩家隐私数据处理、支付和账号相关逻辑。这些任务一旦出错不是改几行代码能补救的。给读者一条最实用的建议AI 生成的每一段代码你都要在心里回答三个问题。这段代码放在哪个文件它在什么时候被调用如果运行失败第一步日志应该出现在哪里能回答这三个问题说明你已经理解了这段代码的逻辑AI 给你的是可维护的代码回答不了说明你只是复制了一段自己看不懂的内容它迟早会在某个上线前夜变成无法定位的 bug。工程层面的最佳实践还可以再补充几条存档数据从一开始就写入版本号。哪怕现在只有一份存档也要预留 version 字段否则后续加新字段时会出现旧档全部作废的尴尬。所有数值常量集中在 GameConstants 类。放置游戏调数值非常频繁常量散落在各个脚本会让 AI 补全和人工排查都变得困难。离线收益必须有上限。这是放置游戏的底线设计没有上限的离线收益会在第一个假期毁掉整个游戏的经济系统。大数字格式化要提前实现。放置游戏运行几天后数值就会突破百万直接显示完整数字会让 UI 失控。产出逻辑使用累加器而不是每帧累加。每帧累加会让产出速率受到帧率影响低端手机上会产生明显差异。用协程或定时器替代 Update 中频繁的字符串拼接和 UI 刷新。UI 刷新频率控制在每秒一次即可不需要每帧刷新。上线前模拟时长跨天和跨平台的存档迁移。时间字符串解析、时区差异在测试中很难被注意但玩家真实环境里一定会遇到。从项目管理角度看建议保留所有与 AI 的对话记录按模块归档。这不是为了证明“游戏是 AI 开发的”而是因为 AI 生成的代码往往没有注释重新阅读时只能靠对话上下文理解当初的设计意图。这些记录就是最真实的开发文档。9. 复盘与下一步安排《细菌克星》上线后我复盘发现 AI 真正节省的不是“写代码”的绝对时间而是“从想法到可运行原型”的反馈时间。放置游戏的乐趣在于数值成长但数值曲线是否舒服必须跑起来才能感知。过去改一版数值需要改代码、重新编译、重新跑挂机模拟现在把需求描述给 AI几分钟就多一个可测试版本。这种高频反馈才是 AI 辅助开发最大的杠杆。如果你也想验证自己能否独立做完一款上架 Steam 的游戏最务实的路线不是先花两个月学完一套完整课程而是直接用 AI 搭一个最小可玩版本一个画布、一个按钮、一个产出管理器、一个存档管理器先跑通“点击—产出—升级—离线收益”的循环。这个循环成立之后再花一个周末接入 Steamworks把游戏变成能从 Steam 商店页启动的产品。上线只是开始。下一步值得投入的方向有三个检验数值曲线和玩家留存数据根据真实反馈调整 AutoGrowth 和升级成本把成就系统和 Steam 成就打通给玩家跨平台的目标感接入 Steam 云存档解决玩家换电脑后的存档迁移问题。这些功能对应的技术门槛都不高但每一项都能明显提升一款放置游戏的生命周期。做完这些《细菌克星》这个项目的完整开发链路才算真正闭环而你也可以说自己完整地经历了一款从 AI 辅助开发到正式上线的游戏产品。