1. 第七周的项目快照:游戏没做完,但终于敢给别人看了
先说结论:这是我用 AI 编程做独立游戏的第七周,游戏还没有做完,但已经能跑通一个完整的 demo 循环:标题界面 → 选人 → 进关卡 → 打三波怪 → BOSS 战 → 结算 → 回到标题。画风还是那个丑萌的像素风,代码量大概在 8500 行左右,其中我手写的大概只有四成,剩下的都是 AI 生成的——但我要强调的是,AI 写代码这件事,真正的难点从来不是让它写出代码,而是让它别把代码写得让你后面没法改。
这个系列前面几篇,我聊过怎么选 AI 编程工具、怎么设计提示词、怎么让 AI 理解游戏的整体架构。这篇我想换个角度,专门讲讲当项目从"跑得起来"走向"玩得下去"时,你会遇到的那些破事。因为前六篇如果你照做了,这时候你的处境应该和我一样:游戏能玩,但帧率忽高忽低,内存像漏水的水桶,同一个 UI 界面改了三遍还是不满意,AI 修改一个 bug 的结果往往是引入两个新 bug。
这期内容,我打算用我自己的项目当解剖对象,聊聊中途接手自己一个乱糟糟的代码库、用 AI 做性能优化、以及在"AI 效率极高"和"AI 失控瞎改"之间来回横跳的完整经历。不管你是准备用 AI 做游戏、做工具还是做网站,这篇里的排查思路和踩坑清单应该都通用。
先交代一下项目背景。我做的是一款 2D 像素风的轻量 Rogue 弹幕游戏,玩法核心是躲弹幕 + 三选一强化,给玩家的目标是一局控制在 15 分钟内。按照我的规划,这类游戏是最适合一个人 + AI 来做的类型:美术素材可以用现成像素包,玩法逻辑不复杂但足够有深度,性能瓶颈非常明确(弹幕数量、对象池、GC 分配),每一项都特别适合让 AI 帮忙。
但正是在这个阶段,暴露出的问题让我意识到,AI 编程项目的"先甜后苦"期到了。前几周 AI 生成代码的速度让我产生了"一个人顶一个工作室"的错觉,第七周则是这种错觉破产、回归冷静的一周。所以这篇文章的标题叫"AI 编程来了,我决定一个人做一款游戏(07)"——不是因为我终于做完了,而是因为我终于开始理解,AI 编程时代一个人做游戏,真正的核心竞争力变成了什么。
2. 亲手给自己埋的雷:AI 生成的代码攒够 5000 行之后,开始互相打架
先说一个可能让你意外的事实:AI 编程的第六周和第七周是完全不同的体验。第六周之前,AI 就像一个 "everything expert",你问什么它答什么,一整块功能从零实现,几十行、几百行,跑起来几乎没问题。到了第七周,项目代码量上来之后,AI 开始频繁翻车,而且翻车方式极其统一——不知道项目其他地方长什么样,于是在修改 A 模块时破坏了 B 模块,或者在生成新功能时根本没有和已有系统对齐。
这事儿的根源,我得从人的角度先说透。一个人用 AI 做项目,最危险的心理是"代码不是我写的,所以我不需要完全理解它"。前几周我确实偷懒了:AI 生成一大段代码后,我跑通测试就满意地收工了,根本没有认真读每一行。于是到第七周,代码库的"心智模型"只有 AI 有,我只有大概的印象——这就是一个巨大的坑。
2.1 症状清单:当 AI 代码库开始"失控"
我先整理一下这个阶段的典型症状,你如果也走到这一步,应该会感到熟悉:
- 症状一:反复出现的"灵异 bug"。某个敌人的子弹明明只在关卡 2 出现,却在主菜单界面偶尔闪出来一帧。查了半天发现,是 AI 早前生成一个"全局限时管理器"时,把子弹池的初始化逻辑写得过度"全局化",结果所有场景都共享了它。
- 症状二:改一处,崩三处。我让 AI 加一个"拾取金币飘字"效果,它很听话地在 HUD 里加了一个飘字组件,结果进入结算界面就报空引用。原因:结算界面的 HUD 初始化顺序和主界面不同,飘字组件在它引用的 UI 画布加载之前就被实例化了。
- 症状三:AI 开始"遗忘"以前的约定。项目的输入系统我早就统一成"Config 配置按键 → InputManager 读取",但 AI 为了省事,在新生成的技能系统里直接写了
Input.GetKeyDown(KeyCode.Space)。单看这一处没问题,可我在把技能系统改成支持手柄时就蒙了,因为硬编码按键完全绕开了我设计的输入映射层。 - 症状四:代码量膨胀到难以理解。有一回我让 AI 帮我重构一个敌人波次生成器,它没有简化逻辑,反而生成了一个 800 行的"波次配置解释器",读起来比原来的 200 行还难懂,而且运行效率更差。
2.2 病根排查:AI 的"局部最优"和"上下文窗口限制"
这些症状,说到底根子在两点。
第一,AI 本质上是"局部最优"的生成器。它每次生成一个函数,都倾向于在当前上下文范围内做最合理的实现,但它并不知道全局架构你的系统里还有别的什么模块。如果你不提供全局信息,它就会默认使用它的"常识"来填空——而这恰恰会破坏你项目早就定下的约定。
第二,上下文窗口限制。目前市面主流的 AI 编程助手,单次能"看到"的代码上下文通常是整个文件,少数能跨文件检索,但它们毕竟不是人,无法像你一样把项目几千个文件之间的关系烂熟于心。所以当你让它"改一下那个 BOSS 的 AI 脚本"时,它可能只看得到 BOSS 的 AI 脚本,根本不知道你的"伤害数值系统"里面有一套"受伤无敌帧"的逻辑。结果它把 BOSS 的受伤反应改完之后,无敌帧失效,玩家一碰到 BOSS 就掉血飞到屏幕外。
2.3 对症下药:给 AI 立"全局规矩"的确切做法
发现问题以后,我做的第一件事不是继续干活,而是花了两天时间做了一件事:给 AI 立规矩。具体操作如下,你可以直接照抄。
第一步,我建立了一个GLOBAL_RULES.md,放在项目根目录下,然后在每个让 AI 执行任务的提示词开头,都让 AI 先读这个文件。文件里写的内容包含:
- 项目的整体模块划分(哪个目录管什么)
- 编码规范(命名风格、接口约定、文件大小上限)
- "禁止做的事"清单:例如禁止硬编码输入、禁止在游戏逻辑脚本里直接操作 UI 对象、禁止在 Update 里分配新对象、禁止修改与本次需求无关的文件
第二步,要求 AI 在每次改动之前,先用文字解释自己的方案,说得通才允许动手。我之前太着急,总让它"直接改",现在强制它先写方案再说。这条看起来费时间,实际上省下的返工时间远多于多花的这点时间。
第三步,"改到什么程度可以停"必须定义清楚。我的规则是所有改动必须保持"单一职责",AI 不能在修 bug 的时候顺手"优化"了整个模块的代码风格。风格统一这件事可以之后专门开一个任务做,混在一次改动里,出问题都查不清是谁的责任。
这一步很关键,我们单独拿出来继续说。我平时在正常工作里也带过几个人,我发现让 AI 和我带过的"高级工程师"有不少惊人的相似之处:能力很强,但正常发挥需要清晰的上下文、明确的范围限定、还有对全局架构的了解。这不纯粹是技术问题,更是管理问题。
个人经验:给 AI 立规矩这件事,越早做越好。我是在代码量到 5000 行才做,晚了。如果你刚开始用 AI 写项目,第一周就建
GLOBAL_RULES.md,后面至少能少走一半弯路。
3. 用 AI 做性能优化:一次"手术式"的 Unity 帧率排查实战
第七周最重要的事情,是给游戏做了一次系统性的性能体检。在这之前,游戏在单位台式机(AMD Ryzen 5 + GTX 1660)上能跑到 60 帧,但一进弹幕密集的 BOSS 战就掉到 30 帧。更难看的是,小内存机器上每 30 秒会卡顿一下,那个卡顿的时间点非常规律,跟弹幕密度无关,就是纯粹的资源抖动。
对独立开发者的游戏来说,帧率不稳比平均帧率低更致命——玩家可以接受 45 帧恒定,但绝对不能忍受 60→30→60 来回跳。因为帧时间波动直接反映到手感上,而动作游戏的"手感"是命根子。
3.1 第一步:先量化,再优化
我一上来没有急着让 AI 改代码,而是先给它一份"性能报告"的数据。Unity 的 Profiler 是我用的主要工具,在Window > Analysis > Profiler打开,然后在 BOSS 战场景中跑 3 分钟,采集帧时间、CPU 耗时、GC 分配三个指标。
不量化就没有优化的依据。如果你直接跟 AI 说"帮我优化性能",它给你的建议十有八九是洗稿级别的:用对象池、合并 Draw Call、压缩贴图——这些泛泛之谈确实没毛病,但解决不了你的具体问题。
让数据说话之后,我得到了一份比较详细的问题清单:
| 指标 | 优化前数值 | 问题粗略定位 |
|---|---|---|
| 帧时间均值 | 34ms(约 29 FPS) | 主要卡在 BOSS 弹幕施放逻辑 |
| 帧时间峰值 | 89ms | 大量瞬时的 GC Alloc |
| 平均 GC 分配 | 每帧约 2.3MB | 弹幕发射器在 Update 里创建临时对象 |
| Draw Call 数量 | 约 287 | 每个子弹都是独立 SpriteRenderer |
| 内存峰值 | 约 890MB | 加载了 16 个关卡场景,从不卸载 |
这份数据打给 AI,它的分析就完全不一样了。它不再给泛泛的优化建议,而是直接指出:GC 分配每帧 2.3MB 是最大的性能杀手,单帧 89ms 的尖刺就是 GC 收集引起的;Draw Call 287 是另一个瓶颈,但优先级略低;内存峰值高是因为场景没有做按需卸载。
3.2 第二步:解决子弹海啸——对象池 + 缓存
我按照优先级,先从 GC Alloc 和弹幕对象池着手。我的弹幕系统一秒要发射 80~120 颗子弹,每颗子弹都是一个EnemyBullet对象,里面有 transform、sprite renderer、移动速度属性。优化前,每发射一颗子弹就new一个对象,子弹销毁时还要标记Destroy,然后等 Unity 的卸载机制来收拾它。
这里的高效做法是对象池。我把"创建子弹"的逻辑统一改成:
- 预创建 300 个
EnemyBullet实例放进池子 - 发射时不
new,而是从池子中取一个激活 - 子弹出屏或碰撞后用
SetActive(false)归还
具体的代码如下,这套代码是我让 AI 根据项目现有弹幕系统重构的,但我在关键位置做了检查和微调,确保它真能用:
public class BulletPool : MonoBehaviour { public GameObject bulletPrefab; public int poolSize = 300; private Queue<GameObject> pool = new Queue<GameObject>(); void Awake() { for (int i = 0; i < poolSize; i++) { GameObject bullet = Instantiate(bulletPrefab); bullet.SetActive(false); pool.Enqueue(bullet); } } public GameObject GetBullet(Vector3 position, Quaternion rotation) { if (pool.Count == 0) { // 池子不够用,临时扩容。实际开发中最好在 Loading 阶段就设好峰值。 GameObject extra = Instantiate(bulletPrefab); pool.Enqueue(extra); } GameObject b = pool.Dequeue(); b.transform.position = position; b.transform.rotation = rotation; b.SetActive(true); return b; } public void ReturnBullet(GameObject bullet) { bullet.SetActive(false); pool.Enqueue(bullet); } }千万别小看这几行,它是 AI 最常写错的一个逻辑点。AI 默认的写法经常在GetBullet方法里Instantiate新的子弹、在ReturnBullet里写Destroy,那就是一个披着对象池外衣的"普通子弹生成器"——没有任何优化效果。所以这个代码我验收时专门多看了两遍。
另一个重要问题是:如果池子里子弹不够怎么办?我一开始设为 300,但测到最高难度 BOSS 战时,峰值一口气生成 450 颗子弹,池子不够导致临时 Instantiate,又出现了卡顿。所以最终我把池子预生成调到 600,并且额外写了一段预警逻辑:如果某次取用后剩余池中对象少于 10%,就打印一条日志,提醒后续要不要再加。
3.3 第三步:让 AI 重构子弹移动的 Update 循环
对象池解决了对象创建的 GC 问题,但还有一个问题:每颗子弹自己的移动逻辑是在各自的Update()里做的。600 个子弹就有 600 个Update()调用,虽然每帧加起来时间不长,但 Unity 的MonoBehaviour.Update()调度成本会随着对象数量线性增长,累计起来不可忽视。
我让 AI 把这个移动逻辑重构成一个统一的BulletMovementManager,用"把子弹的 Transform 缓存到数组里,在 Manager 的 Update 里统一遍历移动"的方式。类似数据导向设计的思想,把分散的逻辑集中管理。
重构之后的效果,同一场景下再跑 Profiler:
| 指标 | 优化前 | 优化后 | 下降幅度 |
|---|---|---|---|
| 平均 GC 分配 | 每帧 2.3MB | 每帧 90KB | 96% |
| 帧时间均值 | 34ms | 17ms | 50% |
| Draw Call(后文解决) | 287 | 146(贴图合并后) | 49% |
| 帧时间峰值 | 89ms | 28ms | 68% |
数据明显向好了。但别着急高兴,紧接着我发现原生问题解决之后,新的瓶颈暴露出来了——Draw Call。这也印证了性能调优那条老路:永远不会只改一处就万事大吉,优化完 A,B 就会变成主要矛盾。
3.4 第四步:动态合并 UI 和子弹的渲染批次
UI 的优化其实不复杂。我的项目里 UI 元素非常多,每个Image、Text都是一个独立的渲染单元,如果字体的 atlas 分散,或者 UI 上有大量需要频繁更新的文本,合批会非常困难。
我把所有 UI 做了三件事:
- 减少不必要的 Raycast Target:给所有纯展示用的 Text 和 Image 关掉 Raycast Target。这样鼠标和触摸检测的命中测试就不用扫描这些对象,省下不少 CPU。
- 控画布重构频率:UI 上如果每帧都有文本变化(比如分数、血量),这个 UI Canvas 就会每帧做一次重构。我把分数从"每帧更新"改成"只在数值变化时更新",直接在
Text.text的 setter 入口判断:如果值没变,就跳过赋值。 - 缩小 UI atlas:一顿裁剪之后,所有 UI 共用一张图集,减少纹理切换的次数。
至于场景中大量的子弹精灵,方案其实是合并动态批次。思路是让同一种贴图的子弹尽量连续渲染,避免频繁切换材质。我在子弹池的排序逻辑里做了一点小优化,比如让所有同种子弹在数组里排在一起,发射时也按类型批次取用。这个改动配合 Sprite Atlas 图集,直接让 Draw Call 从 287 掉到 146。
另外,场景内存的问题我也顺手处理了:Unity 的SceneManager.LoadScene默认把旧场景直接卸载,但如果你用 Additive 方式加载或者有全局 DontDestroyOnLoad 对象没管好,内存就会越涨越高。我审查后发现,老版的"关卡波次配置"数据全都被我设成了static字段,每进一关就在 static 列表里追加一份配置,从不清理。这会直接导致内存随着游戏局数增长,一局还好,三局下来就逼近 1GB。修复方式:在关卡开始时清空静态配置缓存,只保留当前关卡的引用。
3.5 性能优化的核心心得
这一段优化做下来,我对用 AI 做性能调优的体会是:AI 是很好的执行者,但你要当好架构师和验收者。性能问题本质上是数据问题,你需要先通过 Profiler 定位出哪个数据不对(GC、DrawCall、内存峰值),然后让 AI 针对这个明确的数据动手。它不会自动发现"每帧 2.3MB GC 分配来自子弹创建"——它没有读你的全部代码,更没法像人一样做全局判断。
所以我的工作流变成:拿 Profiler 数据 → 自己分析瓶颈归属 → 给 AI 明确的修改指令 → 跑 Profiler 验证 → 有提升则接受,没提升则继续挖数据。这套流程和传统开发没有本质区别,关键是 AI 能把从"指令到修改"的速度提高好几倍,让你能在一个晚上迭代三轮优化方案。
4. 越补越多的"AI 修 bug"循环:我的排查链路与防退坡机制
前面讲性能优化,是一切顺利时的节奏。这一章我要讲讲最折磨人的事:AI 改 bug,改着改着把原本稳定的系统改崩了。这个环节里踩的坑,我希望能帮你省下至少两天的无头绪时间。
4.1 一次典型"AI 连环翻车"事件复盘
我的技能系统里有一个很简单的需求:玩家按 Q 键释放一个短距离冲刺,冲刺时获得无敌帧,持续 0.4 秒。这个功能两周前就做好了,一直没出问题。第七周我想加一个"冲刺后 1 秒内近战伤害 +30%"的 buff,于是让 AI 改技能系统的代码。
AI 的改动方案是:读到了冲刺技能脚本,在释放冲刺的方法里加了一个buffMgr.AddBuff(BuffType.Strength, 1f, 0.3f)调用。从局部逻辑看,它没错。但我没想到的是,这行代码直接让玩家的冲刺动作在 0.4 秒无敌帧期间多了一个"力量 buff",而"力量 buff"的实现逻辑里又读取了玩家的基础攻击力,基础攻击力在冲刺状态下恰好被另一个 AI 早前写的 "冲刺姿态改变攻击力回退" 的脚本设置为 0,于是玩家冲刺完 1 秒内的攻击力变成了 0,伤害反而变低了。
我刚开始完全没料到这个结果。第一次测试:冲刺后平 A,伤害从 12 变成 0,我以为是自己手滑没打中。第二次测试:还是 0,我才意识到是 AI 改动引发了连锁反应。
这个 bug 的排查过程极其痛苦,因为断裂的链条跨越了四个文件:技能释放脚本、buff 系统、属性系统、角色姿态系统。传统 IDE 里根本没法一眼看出它们的关联。我花了一个多小时逐文件读代码,才最终定位到根源:AI 加的那行代码没有做防御性检查,也没有遵循"获取当前实际攻击力应该走属性系统统一接口"这个项目规则。
4.2 排查链路:从"现象"到"根因"的四步法
我把这轮排查总结成了四步,现在每次让 AI 改完代码、测试挂了,我就按这套流程走,效率高多了:
第一步,复现并锁定触发条件。不要凭感觉改代码,先把"什么操作、什么状态、什么次序下会触发 bug"记录清楚。我建了一个0_bug_repro.md文件,每发现一个新 bug 就把复现步骤写进去。很多 bug 的触发条件是你没料到的,写下来之后才能让 AI 也快速定位。
第二步,用版本控制快速定位改动范围。我每次让 AI 改完代码,都会把改动单独提交到一个分支上(分支名就叫feat/buff-attack-percent),然后核心分支保持稳定。如果新改动一出问题,我直接git diff看这个分支的改动,比从头梳理代码快几个数量级。这一步极度关键——AI 改代码经常偷偷改到无关文件,版本控制能让你立刻发现。
第三步,让 AI 解释自己的改动,并追问接口约束。当 bug 定位到某个改动时,把改动片段贴给 AI,然后问它:"你这次改动依赖了哪些现有接口?这些接口在什么情况下可能返回非预期值?" 这一步常常能直接让 AI 自己发现自己违规了。
第四步,在 AI 的修复之上加防退坡测试。修复 bug 后,一定不要只验证"能跑",还要写一个最小化的单元测试或集成测试。哪怕只是一个极简的 sanity check:冲刺后攻击力不应为 0。这样以后再有 AI 代码改动,测出回归时你能立即发现。我称为"防退坡测试"——防止 AI 每次修改都把项目往"坡下"推一点,最终把游戏改回一个不可玩的烂摊子。
下面是这套流程可视化的关键节点(我画图功力有限,你能看懂就行):
发现 bug 现象 ↓ 记录复现步骤(写进 0_bug_repro.md) ↓ git diff 查看最新改动范围 ↓ 把改动片段贴给 AI,让它解释依赖关系 ↓ 定位根因(通常是接口约束或全局规则被破坏) ↓ 修复 + 写防退坡测试 ↓ 回归验证,更新文档4.3 为什么 AI 最容易在这里翻车,以及如何预防
AI 修 bug 容易翻车的原因,其实可以总结成一句话:它默认"改动是局部的",而游戏代码天然是"全局耦合"的。任何牵一发而动全身的系统——属性、Buff、状态机、输入映射、UI 事件,AI 改起来都容易出问题。
预防方式我目前验证有效的有三个:
一是强制 AI 在改动前做依赖分析。我要求 AI 在提示词里回答一个问题:"你这次改动会影响哪些其他系统?影响面是否可以控制在当前模块内?" 如果它不能明确回答,就别让它动手。这一条可能让 AI 的回答速度变慢,但正确率大幅提升。
二是把高风险模块设计成"窄接口"。比如 Buff 系统,我把它封装成只提供AddBuff(BuffType, duration, magnitude)这样一个入口,内部逻辑不许外部直接访问。这样 AI 如果要调用 buff 系统,只能走这个窄接口,不容易意外耦合到内部状态。这和写后端服务的思路完全一样——降低模块间耦合,AI 就不容易踩雷。
三是永远保留一个能回滚的稳定分支。只要 AI 改动导致测试失败,立刻把主分支切回上一版,别跟 AI 在错误的代码上反复拉扯。很多时候我们就是太想"修好这个错误",却忘了直接把改动 revert 掉、重新换个提示词让 AI 生成,反而更快。
实战心得:让 AI 修改问题的成本,往往低于让它"接着刚才的思路修复问题"。如果一次改动失败,我会立刻重置会话、换个思路重来,而不是在同一个错误方案上继续要求"修好它"。因为 AI 在同一个会话里往往会固执地延续自己的方案而不自知。
5. 提示词从"写功能"切换到"填坑模式":几种高价值提示词模板
既然已经聊到 AI 怎么改 bug,这一节就把我第七周摸索出来的几种"填坑模式"提示词分享给你。这和最初"帮我实现一个功能"的提示词完全是两种生物,如果你还在用 Last 方式指挥 AI,你很快就会遇到"AI 越修越乱"的崩溃感。
5.1 面向现有代码做改动时的提示词结构
先说底层逻辑:AI 在"已有代码"上做改动时,最关键的信息不是"你想要什么效果",而是"你不知道但它必须知道的全局信息"。所以我会把提示词拆成四段:
【任务】 修改文件:Assets/Scripts/SkillSystem/DashSkill.cs 需求:玩家使用冲刺后 0.4 秒无敌,同时获得 1 秒的 30% 伤害加成 buff。 【项目规则(强制阅读 GLOBAL_RULES.md)】 - 所有战斗数值必须通过 AttributeSystem 统一获取和修改,禁止直接操作 raw 字段。 - Buff 系统只能通过 BuffManager.AddBuff(BuffType type, float duration, float magnitude) 调用。 - 禁止修改与本任务无关的文件。 【你目前的计划(先回答不要动手)】 请说明: 1. 你打算改哪几个文件?各改什么? 2. 这些改动会影响哪些现有系统?是否有潜在风险? 3. 你的方案如何保证不破坏冲刺无敌帧逻辑? 【验证方式】 改完后,执行 Unity Test Runner 里的 DashBuffSmokeTest,确认冲刺后的平 A 伤害为 15.6(12 * 1.3)。这段提示词有三个关键点。第一,让 AI 先"说计划再动手",这能帮你在早期阶段就发现它打算跑偏的方向,及时叫停。第二,明确告诉它"不能碰哪些文件",杜绝 AI 擅自重构。第三,给出明确的数值验证目标,让 AI 自己判断改得对不对,而不是靠你肉眼测试。
5.2 专门用来"排查"的提示词模板
当 bug 已经出现、但我不知道根因在哪时,我用的提示词是这样的:
我在跑游戏时发现一个 bug: 复现步骤: 1. 进入第二关 2. 击杀第一个精英怪 3. 打开背包(快捷键 I) 4. 游戏报空引用错误:NullReferenceException: Object reference not set to an instance of an object 报错堆栈(已附在下面)。 请根据堆栈和项目代码做根因分析: - 不急着给修复方案 - 先列出:最可能的原因、次要可能原因、每一类原因的排查方法 - 要求你检查这个报错是否与最近的 5 次 git 提交有关 - 分析过程中如果需要查看其他文件,请先列出文件名,再继续这个模板的价值在于强制 AI 做根因分析而不是直接给修复。很多 AI 助手收到"报错了,帮我修"就会立刻给一个局部补丁。但它可能完全没看堆栈、没看上下文,补丁只是缓解了症状,根因还在原地。所以我把"先分析,后修复"写死了,效果显著。
5.3 专门用来"重构"的提示词模板
第七周我还做了一次大重构:把原来散落在各个脚本里的敌人 AI,按状态机模式统一重写。给 AI 的重构类提示词,需要额外强调"保持行为不变"。
重构目标:把 EnemyAIController.cs 里的 switch-case 敌人 AI 改为状态机模式。 约束: 1. 行为必须完全等价。现在的 idel → chase → attack → hurt → die 流程不能变。 2. 不允许改变对外的公共方法名和字段名(其他脚本依赖它们)。 3. 重构后必须保证单测 EnemiesAITests 全部通过。 4. 不要顺手改其他文件。 下面是当前文件的全文: [贴代码] 请先分析状态划分是否合理,如果有更优方案,先说建议,我再决定要不要调整。重构类任务的关键是"等价性验证"。让 AI 重构完,你必须快速跑一遍原有的所有测试,没有测试的话至少手动过一遍原有功能。我在这一阶段吃过一次大亏,AI 重构完敌人生成器,所有敌人类型都正常,唯独精英怪死后不掉落了,查了半天才发现重构时把掉落表的初始化放错了位置。防退坡测试如果当时有,就不至于花两小时定位。
5.4 "AI 不知道的上下文,你得喂给它"
最后必须强调:AI 的上下文窗口是有限的。哪怕这个 AI 号称"项目级上下文",它一次能看的文件数量还是有限制的。所以当你要改一个高耦合模块时,请把关联的接口定义或者关键函数签名贴给它,而不是指望它自己搜。
我的习惯是,提问时直接附上这几样:
- 项目根目录
GLOBAL_RULES.md的全文或关键段落 - 所涉及模块的接口定义(比如 AttributeSystem 的公开方法列表)
- 最近一次 git 提交的 diff(让 AI 知道别人改了什么)
这条习惯让我的 AI 出错率下降得非常明显。
6. 当 AI 从一个"写码工具"变成一个"结对编程搭档":第七周的收获与反思
到了第七周,我对 AI 编程的理解已经发生了很大的变化。差不多可以总结一下这个阶段真正的收获。
6.1 从"让 AI 干活"到"和 AI 一起做决策"
过去我做功能时,是"我提需求 → AI 生成代码 → 我测试验收"。到了性能优化和 bug 修复阶段,这个模式行不通了。因为很多问题你不能简单描述,你得先分析数据、定位问题、想清楚方案,然后才轮得到让 AI 执行。
换句话说,AI 编程的瓶颈不再在"写代码"那个环节,而是在"懂系统"和"做决策"的环节。而这恰恰是人的价值所在。同样是改一个 BOSS 弹幕生成器,AI 可以生成得很漂亮,但是"要不要引入对象池""对象池的初始大小设多少""弹幕的 Move 逻辑应不应该抽离"这些设计决策,AI 做不了——AB 测试的成本太高了,只有你能拍板。
这种分工的感觉,有点像带了一个非常聪明但缺乏经验的实习生。你要把事情拆解成足够小的步骤给它,它就能执行得飞快;但如果你自己都没有全局思考清楚就抛给它,它就会在错误的方向上疯狂输出,然后浪费你更多的返工时间。
6.2 一个人 + AI 做游戏,里程碑式的标记变得更重要
独立开发者一个人做太容易迷失方向了,有了 AI 之后这个风险更严重。因为 AI 一天就能生成一千行代码,但其中真正"有游戏性"的验证,还是需要你亲手玩、亲手调。
在这周里,我给自己建立了一个"每天可玩的版本"机制:每天结束前,主分支必须处于一个"完整可玩"的状态——哪怕只有一关,哪怕只有 5 分钟的游戏内容。这不是为了给别人 demo,而是为了让自己始终有"完整体验"的基准线。如果哪天 AI 改崩了,即使当前任务没完成,也要先回滚到上一个可玩版本。这个机制在 AI 编程时代尤其重要,因为 AI 改崩的几率比你想象的高,如果你不锁定"可玩"这条底线,你会陷入一整个礼拜都在修一堆半成品功能的泥潭。
6.3 给新手的一个建议:别急着冲功能,先冲"稳定"
如果你正在用 AI 做项目,我给你的第七周建议是:在这个阶段,稳定性的优先级应该高于新功能。相比于"再加一个 Boss、再加一个道具",更值得做的是:
- 把核心玩法的性能优化到流畅
- 给关键系统写一套防退坡测试
- 完整跑通一次从开始到通关的流程,把 BUG 清单削到个位数
- 把 GLOBAL_RULES.md 写得足够详细,让 AI 后续只干活、不添乱
这些基础工作听起来不酷炫,也没有新功能那么让人开心。但它们才是"从 Demo 走向可发布游戏"最核心的一步。没有稳定性和性能底子,功能越多,游戏越像一栋地基不牢的危楼,AI 每往上盖一层,你睡得就越不安稳。
就拿我自己的项目来说:如果没有第七周的性能优化和规则治理,第八周我其实可以再做 3 个新 Boss。但那些 Boss 可能在 60 帧的桌面上流畅,在玩家入门级显卡上就变成 PPT。做游戏这行,永远不是"我做了多少内容"算数,而是"玩家实际体验到多少内容"才算数。
如果让我总结第七周的一条核心经验,那就是:AI 可以把你的生产力放大十倍,但同时它也能以同样的倍数放大你架构混乱的风险。代码是自己的,架构更是自己的。AI 永远不会替你背这个锅。
7. 给同样在用 AI 做项目的你:一次真实的周复盘
这周的结尾,按照惯例分享一下项目整体的进度和一些个人反思。不算完整复盘,更像是随手写的工作日记,希望能给同行一些参照。
7.1 本周完成清单
- 核心功能:完成了冲刺 Buff 联动和两个新敌人(追踪弹型、散弹型)
- 性能优化:完成对象池重构、Draw Call 降低至原来的 50%、GC Alloc 降低 96%
- 工程质量:建立
GLOBAL_RULES.md、增加 8 个防退坡测试、重置了 2 次大分支回滚 - 内容量:当前可玩内容约 20~30 分钟一局,5 种敌人、2 个 Boss、16 个强化选项
7.2 下周计划
- 实现第三个 Boss(设计稿已完成,机制是分阶段切换弹幕形态)
- 给 UI 界面增加手柄操作支持(这需要先解决输入系统的硬编码问题)
- 做一次完整的 10 局试玩压力测试,记录崩溃和卡顿日志
7.3 个人反思三则
第一则,AI 的"效率红利"是有保质期的。项目初期你感觉自己在坐火箭,项目中期就开始坐过山车。真正让项目活过中期的,不是某个神奇的 AI 按钮,而是你自己对项目架构和性能的掌控力。
第二则,独舞也有舞伴。AI 编程时代的独立开发者从来不是真的"一个人"。你带的 AI 搭档,需要你用管理思路去对待:目标分解、规则设定、结果验收、回归测试。这几个动作做到位,AI 就是超级生产力;做不好,你就是"一个人为核心的 bug 生产线"。
第三则,游戏设计的灵魂,AI 仍然碰不到。开发到第七周,我做的最多的其实不是写代码,而是玩游戏、调手感、感受节奏:弹幕密度够不够刺激?无敌帧给多了还是给少了?拾取金币的飘字是不是太慢?这些感受全凭人的直觉,AI 无法替你决定。它能够帮你扫清技术难题,让你把时间花在"游戏好不好玩"这个最根本的问题上,这本身就是 AI 编程时代给独立开发者最好的礼物。
所以呢,一个人 + AI 做游戏,到底行不行?目前的答案依然是:行,但你得先做好"手里有一个半懂不懂的实习生"的心理准备,然后用管理者的思维去完成这个项目。第七周的经验就是这些,下一周如果顺利,我再来分享第三个 Boss 的完整实现和试玩压力测试的修复记录。未完待续。