
最近我干了一件特别“离谱”的事用 GPT 6.1 从头写了一个可以玩的《红色警戒》风格即时战略游戏而且已经把完整源码开源出来了。先别急着吐槽说真的这个项目做完之后我自己都挺意外的——不是意外 AI 能写代码而是意外它居然能把 RTS 这种硬骨头啃下来从地图寻路到战斗数值再到 UI 交互最终竟然跑出了一个能对战能推家的可玩版本。我先把话说清楚这不是拿现成引擎改个皮也不是调用某个游戏框架套个壳。整个游戏的逻辑层、渲染层、AI 行为树、寻路系统甚至资源和经济循环全部是基于 GPT 6.1 生成代码并手工整合而成的。项目本身是 Web 实现浏览器打开就能玩跨平台、免安装对局逻辑全部跑在本地代码已经打包好放到开源平台了。这篇文章我会把整个从构思到落地再到开源的经过完整拆一遍包括技术选型是怎么想的、Prompt 是怎么写的、哪些环节最容易翻车、以及最后是怎么把代码质量打磨到可以见人的程度的。无论你是对 AI 辅助开发感兴趣还是单纯好奇 RTS 游戏底层是怎么运作的这篇都能给你一点实打实的东西。1. 项目整体设计与思路拆解1.1 为什么偏偏选了 RTS 这种硬骨头很多人一听说“用 AI 写游戏”第一反应是做个贪吃蛇或者弹球小游戏。说实话那种项目我也试过让 GPT 写一个贪吃蛇确实几分钟就能跑起来但做完之后毫无成就感本质上就是在复制一个已经被写过无数次的东西。做“红警”的念头来自于一次很偶然的闲聊朋友说现在的 AI 写代码越来越厉害但充其量就是写写工具函数和页面组件稍微带点状态机的游戏逻辑就会开始胡编。这句话我记下了但心里不服气——RTS 游戏在编程领域被称为“交互复杂度之王”背后涉及网格地图、单位寻路、碰撞检测、战斗结算、资源管理、AI 策略等多个核心系统联动如果你能把这个东西用 AI 辅助从零做出来那才真正说明 AI 辅助开发已经跨过了玩具级门槛。选定《红色警戒》风格还有一个现实原因类型足够经典。几乎所有玩家对红警的底层玩法都有直觉认知采矿、造兵、推家、开图。这种强烈的认知模板帮我省了大量需求描述的时间——我不用跟 GPT 解释“什么是即时战略游戏”“为什么要集结点”它训练语料里本身就包含了海量 RTS 相关的代码和设计模式相当于站在一个非常成熟的语义基座上工作。1.2 技术方案选型用什么壳子装这颗心技术栈的选型直接影响整个项目走向我大概对比过三条路线最后选了一条最省心也最适合 AI 辅助的。第一条路线是 Unity C#。优势是引擎成熟、网上资料多、红警同人项目一抓一大把但问题也很明显Unity 的工程结构极其复杂脚本生命周期、Prefab 系统、资源管线这些概念即使让 GPT 来写也免不了大量手工拖拽和装配工作AI 生成的代码大概率没法直接融合进庞大的引擎架构里。OpenRA红警的开源重制版源码倒是现成的但那叫“二次开发”不叫“从零写一个”违背了我定义这个项目时的最初动机。第二条路线是 Python Pygame。语法简单、GPT 生成代码的正确率高但 Pygame 做 RTS 有三个致命伤性能捉急单位一多就卡成幻灯片、跨平台分发困难要装解释器和依赖、Web 化几乎没有可能。做游戏的人都知道RTS 玩家最看重的就是“千军万马”的流畅感性能天花板太低这个项目注定走不远。第三条路线就是我最终选择的纯前端 Web 实现核心游戏逻辑用 JavaScript 编写Canvas 2D 负责渲染没有任何运行时依赖。为什么这条路最对原因有三。第一浏览器的 Canvas 2D 性能其实比很多人想象的好得多用简单脏矩形和缓冲优化跑几百个单位完全没有压力而 RTS 的地图操作天然适合 Canvas 做网格化渲染。第二Web 项目不存在平台分发问题写完了往静态托管平台一扔链接发过去任何人打开就能玩开源之后别人 Clone 下来也不需要配置任何环境。第三也是最重要的JavaScript 生态里没有强制的“工程化范式”一个 HTML 里既能写逻辑也能调渲染GPT 对单文件代码的完整生成能力是最强的这大大降低了 AI 产出代码与项目结构之间的摩擦系数。1.3 我把项目切成了几个可以喂给 AI 的模块在实际动工之前我先做了一件很关键的事把整个红警项目拆成一张模块清单。用人话说就是我不可能让 GPT 一次性生成一个 5000 行的巨大文件也不应该在整体架构还没定型之前就让 AI 往一个方向乱写。拆模块这件事的作用是双重的对我自己来说它让我清楚了完成这个项目需要哪些组成部分对 AI 来说每一块都是相对独立、职责明确的子任务Prompt 可以写得非常聚焦。最终我拆出了下面这几个核心子系统地图系统负责生成和管理战场网格包括地形类型平原、山脉、水域和宽度高度参数单位系统处理所有单位的属性、行为、生命周期和移动逻辑从步兵到坦克都挂在这棵树下寻路系统解决“从 A 点到 B 点怎么走”的问题要求能绕开障碍物并支持大量单位同时寻路战斗系统是伤害计算和攻击行为的总调度包含射程判定、攻击间隔和开火特效AI 系统负责电脑玩家的决策逻辑包括扩张、造兵和作战资源与经济系统管矿场、矿石、建造消耗这些数值关联的东西UI 交互系统接住鼠标点击、框选、命令下发的最小可用界面。这个模块划分思路在这个项目里被反复验证了——模块边界越清晰Prompt 里让 AI 生成的东西就越不会跑偏。后面你会发现我把这些模块用“垂直切片”的方式一个个交给 GPT 去生成再一步步缝合起来每一步都能验证结果是否可用。2. 核心系统实现与代码拆解2.1 地图载具网格系统与资源绘制先说地图模块。RTS 的地图和棋盘的底层逻辑几乎一模一样本质就是一个二维网格数组每个格子记录自己的地形类型和状态。为了方便后续寻路和 AI 模块复用地图的数据结构和渲染分离是必须的——数据层就是一个纯数组渲染层才负责在 Canvas 上画颜色。GPT 生成的地图初始化代码非常规整这里我把核心逻辑提炼出来class GameMap { constructor(width, height) { this.width width; this.height height; this.tiles []; // 核心用一个二维数组存储每个格子的地形类型 // 0 平地, 1 山脉(不可通行), 2 水域(不可通行) // 3 矿石区(可通行且可采集) for (let y 0; y height; y) { this.tiles[y] []; for (let x 0; x width; x) { this.tiles[y][x] 0; } } this.generateTerrain(); } generateTerrain() { // 使用简单的噪声函数生成连续地形区域 // 并不是随机撒点而是用perlin-like模糊制造山脉与水系 const seed Math.random() * 1000; for (let y 0; y this.height; y) { for (let x 0; x this.width; x) { const noiseVal this.smoothNoise(x / 12, y / 12, seed); if (noiseVal 0.25) this.tiles[y][x] 1; else if (noiseVal 0.85) this.tiles[y][x] 2; else if (noiseVal 0.65) this.tiles[y][x] 3; } } } }这段代码的思路很典型不是把地图随机撒满障碍物而是通过平滑噪声函数让地形产生连续的自然感。山脉和水域连成片矿石散布在特定海拔区域这样地图更容易形成天然的攻防通道和资源争夺点玩起来才有红警的味道。数据层设计是纯数值的渲染层只是按照 tile 数值填色我让 GPT 在渲染时又加了一层“近似色抖动”的逻辑——相邻格子的颜色会在一个很窄的范围内浮动远看有纹理感而不是死板的色块。这个模块是整个项目的地基后面所有的寻路和 AI 逻辑都建立在地图数据之上所以务必保证数据访问接口简洁统一。我在这里做了一次小的重构把所有对map.tiles[y][x]的直接访问统一封装成getTile(x, y)和isWalkable(x, y)这种语义明确的方法后面三四个模块都因此省了大事。2.2 单位对象数据模型与状态流转单位的对象模型是整个游戏里最容易被 AI 写飘的部分。很多 AI 生成的游戏代码习惯性地把单位设计成一个巨大的类里面堆了移动速度、攻击力、血量、冷却时间、生产费用、图像颜色、动画帧等全部字段。这种写法在小规模 demo 里没问题但一旦单位类型多起来维护和扩展都会失控。我给 GPT 的指令里特别加了约束单位状态和行为逻辑必须拆开属性走配置行为走方法。用一个配置表定义每种单位的基础数值单位实例只负责持有动态状态。// 单位类型配置表所有数值集中管理 const UNIT_TYPES { rifleman: { hp: 50, speed: 1.2, damage: 8, range: 80, cost: 100, cooldown: 600, color: #4a9e5c }, tank: { hp: 150, speed: 0.9, damage: 25, range: 110, cost: 500, cooldown: 900, color: #5b6d47 }, harvester:{ hp: 120, speed: 0.6, damage: 0, range: 0, cost: 400, cooldown: 0, color: #d4a017 }, turret: { hp: 200, speed: 0, damage: 20, range: 140, cost: 300, cooldown: 700, color: #7a7a7a } }; class Unit { constructor(type, x, y, owner) { this.type type; // 关键不是每个单位都复制一遍所有属性字段 // 而是共享config里的静态数据 this.config UNIT_TYPES[type]; this.x x; this.y y; this.owner owner; this.hp this.config.hp; this.state idle; // idle / moving / attacking / harvesting / dead this.path []; this.target null; this.attackTimer 0; this.alive true; } }共享配置表的设计对后续平衡性调试特别友好。最后我调数值平衡的时候只需要修改UNIT_TYPES里的几个数字整局游戏的体验就会立刻改变不需要满代码库搜索硬编码数值。AI 生成代码时很容易在状态流转那里犯迷糊所以我专门在 Prompt 里画了一条行为链闲置状态下收到移动命令就进入移动移动到达终点附近就回到闲置攻击范围内出现敌方单位就停下并发起攻击攻击打死目标后继续移动或回到闲置采矿车在矿区和精炼厂之间来回切换采集状态。这样一条一条写清楚AI 生成的状态机基本就不会打架了。实际运行里最容易被忽视的其实是“死亡”状态。单位血量归零后要立刻从渲染队列里移除、从单位列表中删除、格子占用标记清空这三件事必须做成一个原子操作否则就会出现“尸体还挡着路”或“死了还能被打”的笑话。2.3 寻路系统BFS 与 A* 的实际取舍寻路是 RTS 里最容易出戏的环节。单位卡墙、转圈、重叠是低级问题稍微高级一点的是大量单位同时寻路时性能崩盘。我让 GPT 先写了一个基础版本基于 BFS 的四方向寻路。为什么最初不上 A*因为 BFS 的实现简单到不可能出错而且在小地图规模下例如 64×64 的网格BFS 的搜索空间完全可控。function findPath(map, startX, startY, targetX, targetY) { const queue [{ x: startX, y: startY, path: [{ x: startX, y: startY }] }]; const visited new Set(); visited.add(${startX},${startY}); const dirs [{ dx: 1, dy: 0 }, { dx: -1, dy: 0 }, { dx: 0, dy: 1 }, { dx: 0, dy: -1 }]; while (queue.length 0) { const current queue.shift(); if (current.x targetX current.y targetY) return current.path; for (const { dx, dy } of dirs) { const nx current.x dx; const ny current.y dy; if (!map.isWalkable(nx, ny)) continue; if (visited.has(${nx},${ny})) continue; const newPath [...current.path, { x: nx, y: ny }]; queue.push({ x: nx, y: ny, path: newPath }); visited.add(${nx},${ny}); } } return null; // 无法到达 }这里存在一个真实工程里必须处理的性能坑[...current.path]在每层扩展时都会拷贝整个路径数组地图大的时候 BFS 的路径数组会不断膨胀这在单位数量多时会拖垮内存。我后来用了一个经典优化——不直接把路径存在队列节点里而是用一个“前驱节点表”搜索完毕后再从终点倒推回溯出整条路径。把这段优化思路作为反馈给 GPT 之后它很快给出了改进版本寻路系统的性能直接翻了几倍。从 BFS 换成 A* 是在多单位寻找目标之后发生的。BFS 在 64×64 地图上对单个单位没问题但 50 个单位同时寻路时每一帧需要的计算量就绷不住了BFS 要扩展到整个网格才能确定最短路径A* 凭借启发函数可以更早收敛。A* 的启发函数我用的曼哈顿距离因为地图只允许四方向移动曼哈顿距离是 完美且一致的启发函数。目前版本的性能足够支撑一局游戏上百个单位同时寻路每帧耗时稳定在几毫秒级别配合 Web Worker 异步寻路其实也不是必须的。2.4 战斗数值攻击命中与伤害结算的隐藏逻辑战斗系统做得好不好直接决定这个“红警”有没有魂。最开始 GPT 生成的战斗代码极其朴素单位进入攻击距离后直接扣血双方站着对撸直到一方倒下。这跟红警的战场体验差了十万八千里。我调整的思路是把攻击拆成几个阶段并逐个在 Prompt 里说明。首先是接敌判定单位不是一进入射程就攻击而是需要一个朝向目标的过程。其次是攻速窗口每次攻击后要经过冷却时间才能发动下一次这自然形成了双方交火时的交互节奏。然后是伤害生效这一步通过命中检查来决定本轮攻击是否造成伤害。我没引入复杂的弹道和随机 M iss 率而是测试了一套更直观的规则攻击动画播到中点时进行一次射线检测如果目标此刻还在射程范围内就直接扣血。attack(target) { if (this.attackTimer 0) return; // 冷却中 this.attackTimer this.config.cooldown; const dx this.x - target.x; const dy this.y - target.y; const dist Math.sqrt(dx*dx dy*dy); if (dist this.config.range) { const dmg this.config.damage; target.takeDamage(dmg, this); } else { // 目标在攻击瞬间移出了射程范围攻击落空 } }这个设计有一个让我很满意的副产品单位在追击过程中会一边追一边尝试攻击同时由于攻击落空的判定存在不会出现“隔着地图边缘的极限拉扯打伤害”这种失衡情况。步兵集群打坦克的数值被压得很低因为步兵单位刷新多、数量大坦克打步兵则有溅射特效突出反步兵的压制感。这些数值不是我凭空想的是我带着对红警原版的记忆先给 GPT 一版“带方向感的参数表”然后自己反复试玩修改了三四轮才定下来的。血条渲染反馈和受击闪白也是这个阶段加进去的虽然工作量不大但视觉上给玩家的打击反馈立刻立体了这是涂数值时最容易忽略、但玩家感知最强的一层。2.5 AI 对手让电脑学会筑造基地和偷袭RTS 游戏如果没有一个会反抗的电脑对手那基本上就只是个沙盒。红警的魅力一半在竞技对抗一半在与电脑斗智斗勇。AI 模块的设计我分了认知层和决策层两层。认知层负责给 AI 一个“有限的视野”——它不能也就是地图全开的上帝视角而是只知道自己基地周围以及己方单位视野范围内的信息。我用一个简单的遮蔽算法每个单位的侦察半径标记出一个视野集合AI 的寻敌逻辑只能在这个集合内寻找目标。决策层负责完成典型的 RTS 战术动作扩张在资源点附近建矿厂、生产维持军队数量、攻击当兵力达到一定阈值时发起总攻和防守基地被攻击时召回部队。这个“侦查→判断→行动”的循环本质上是一个小型行为树。我的做法是用一段伪代码大纲在 Prompt 里描述整个行为树的流转条件让 GPT 用 JavaScript 实现。以下是简化版class AIController { constructor(player) { this.player player; this.state expand; // expand / buildArmy / attack / defend this.army []; this.attackThreshold 8; } update() { // 认知层更新可见区域内的敌方单位信息 this.updateVisibility(); // 决策层基于当前状态和资源情况决定下一步动作 if (this.state expand) { if (this.player.money 500) { this.buildHarvesterAndMine(); } else { this.state buildArmy; } } else if (this.state buildArmy) { if (this.army.length this.attackThreshold) { this.state attack; } else if (this.player.money 800) { this.produceUnits(); } else { this.state expand; } } else if (this.state attack) { // 选取一个可见的敌方建筑作为主目标 const target this.findBestTarget(); if (target) { this.commandArmyAttack(target); } // 军队伤亡过半则回防休整 if (this.army.length this.attackThreshold * 0.4) { this.state defend; } } } }这套 AI 逻辑不是时刻最优的但非常符合 RTS 的“真实感”。初期电脑优先建经济中期攒兵后期一波流推过来同时为了阻止玩家“龟缩憋大招”我加了一个很狗的条件当 AI 侦察到玩家单位数量 3 倍于己方时AI 会提前发动骚扰攻击逼玩家提前接战。这个设计也让玩家在低难度下不会感到电脑作弊在高难度下又能感受到“被针对”的压力。我采用了难度分级的方式去调节 AI 的扩张速度和攻击阈值而不是直接给 AI 加攻击力和血量难度增长完全靠策略强度的抬升玩家玩起来不会觉得是在打一个数值怪物。3. 实操记录从零开始到跑通对局3.1 我是怎么给 GPT 写 Prompt 的这个项目里最核心的实战技能其实不是写代码而是设计 Prompt。我总结了一套“三步式 prompt 模板”对 GPT 类的对话模型效果特别稳定。第一步是定义角色和约束。每条 prompt 我都会写明“你是一名资深 RTS 游戏开发者请用纯 JavaScript 实现……不要依赖任何第三方库不要使用外部引擎所有代码必须可以嵌入单个 HTML 文件运行”。这个角色的设定让答案的语气和风格直接对齐了。第二步是描述功能需求但绝不给太模糊的描述。与其说“做一个寻路系统”不如说“请实现一个在二维网格地图上寻找最短路径的函数地图用 0/1 二维数组表示可通行/不可通行单位只能上下左右移动输入起点和终点坐标输出路径坐标数组”。越具体生成代码的边缘情况处理越到位。第三步是附上相关的上下文。在写单位类的时候我会把之前生成的地图类的完整代码贴进去明确说明“你已经实现了下面的 GameMap 类现在要用它来写单位移动逻辑”。把前序代码作为上下文喂给 GPTAI 才知道自己现在在哪个工程里生成的东西才自然接得上。这里面有一个极有用的技巧当发现 GPT 写出的代码有问题时不要去人肉修改代码而是把报错信息或错误行为描述反馈回去让 GPT 自己改。这个项目里至少 70% 的 bug 都是通过这种方式消掉的。模型本质上是在对话中被“纠正行为”多轮下来生成的代码会越来越贴合你的数据结构。3.2 垂直切片的开发节奏先跑通再优化最初的版本我做了一个很大的冒险不使用分号拼接架构而是纯粹用垂直切片的迭代方式每一轮都要保证“用户能玩到新增的内容”。第一个里程碑只有一个能移动的黄色小方块地图连网格线都没有。第二个里程碑加入地图渲染和基本寻路点击地图任意位置方块会自动绕过障碍物走过去。这个阶段手感极其粗糙单位移动是带瞬移感的因为寻路没有做平滑插值但基础框架正确这就是最关键的“从 0 到 1”。第三个里程碑加入采矿、精炼厂和建筑建造单位的循环此时已经能体验“攒钱-花钱”的经济系统了。第四个里程碑加入战斗第一个敌人是固定不动的炮塔玩家能造三个步兵去打它。直到第五个里程碑我才让 AI 文明整体运转起来——建造、发展、出兵、战争这个时候第一场完整对局才真正跑通。这种开发节奏的心得是不要指望 GPT 一次生成一个完整游戏那就像要求一个实习生第一次上班就把公司的核心项目写完。你要做的是让每一轮对话解决一个很小的、可验证的问题然后逐步拼接成完整的系统。每次里程碑完成后立刻保存一个版本这个版本是可以回头回滚的安全锚点也不会因为新功能把老功能搞崩而有心理压力。3.3 性能优化的几个关键动作性能问题是 RTS 从“能玩”到“顺畅”之间最大的拦路虎。第一版测试时30 个单位同时移动已经开始卡顿帧率掉到 30fps 以下。我抓到三个核心性能瓶颈。第一个是频繁的 Canvas 全屏重绘。最初的代码在游戏循环的每一帧都调用clearRect清空整块画布再全部重绘地图和单位。地图上的格子数量多、单位数量越多每帧重绘消耗就越大。优化方式是引入脏矩形机制——只重绘上一帧和这一帧状态发生变化的区域静态地图的部分可以预先渲染成离屏 Canvas每帧只需要把地图图块drawImage过来再把移动的单位叠上去。这个简单优化直接让帧率翻了两倍多。第二个是单位之间的碰撞检测。最初每个单位每帧都要遍历所有其他单位判断是否碰撞30 个单位就已经有约 900 次两两距离计算。我改成网格哈希空间划分地图被切成小格子每个单位只跟同格子和相邻格子里的单位做碰撞检测检测次数从 O(n²) 降到了近似 O(n)。第三个是寻路缓存。对于静止障碍物地图同一条路径通常会被多个单位使用我在寻路模块里加了一层哈希地图缓存相同起点终点组合的路径直接复用。这个优化在多个步兵同时去同一个采矿点的时候效果奇佳计算量大幅下降。3.4 开源前的 Code Review 与文档整理游戏能跑通后离“可以开源”其实还有一道很大的坎。GitHub 上烂大街的“能跑的 demo”太多了但如果开源的目的不只是展示而是希望别人能参与贡献或者从中学习代码质量和文档就是必须补的功课。我用了两天时间做这件事。先把所有代码从单 HTML 文件拆成模块化的多个 JS 文件按照 Units、Map、Pathfinding、Battle、AI、UI 六个目录整理。这个过程很痛苦因为最初为了省事很多函数是全局的拆分时要梳理依赖关系但不拆的话后续任何人接手都会头皮发麻。然后是写 README。我放弃了冷冰冰的技术清单式 README而是写了一个“项目背后故事 快速试玩 技术架构图 开发计划”的混合版本。教程型文档很重要我知道很多人拿到代码后会想知道“从哪里开始读起”所以特别加了一个“代码地图”章节告诉读者入口文件是哪几个、核心逻辑分别在哪个目录。开源许可证我选了 MIT。RTS 游戏题材本身不涉及特殊授权问题MIT 对使用者最宽松如果有人想基于这个做二次开发或者学习改造法律限制最小对于一个学习向项目这是最合理的选择。4. 常见问题与排查技巧实录4.1 单位卡死在墙角或者绕着目标原地转圈这是 RTS 寻路中最经典的一类问题。症状是单位接到了移动命令但到了目标点附近后开始原地左右徘徊或者被一个角落卡住不停地抖。这个问题的根因通常不是路径不存在而是单位到达“路径终点”的判定方式太苛刻。如果你的到达判定是“单位坐标必须严格等于终点坐标”那几乎一定会出问题。因为单位移动是离散的每帧前进固定步长最后一帧几乎不可能正好落在终点上。标准解法是引入“到达半径”单位与终点距离小于一个阈值比如 6 像素就算到达。另一个造成转圈的常见原因是寻路网格的粒度与单位的碰撞半径不匹配。单位碰撞半径比网格大但寻路按网格中心行走结果就是路径穿过了“单位实际过不去”的窄缝。这时候要么把碰撞检测半径调小要么把寻路网格做膨胀——把所有障碍物的四个方向都向外扩展一格。4.2 大量单位运动时互相穿插重叠的诡异行为网上 RTS 游戏 demo 最拉胯的观感就是一堆单位像幽灵一样互相穿过。原因就是完全没有单位之间的碰撞响应。但如果你直接给所有单位做严格物理碰撞又会出现堵车死锁——前面单位挡路后面单位全部停住。游戏体验反而不如穿插。我的折衷方案是软碰撞单位之间检测到距离过近时不阻止移动而是施加一个横向的偏移力让它们自动错开。这实现起来很像简易的斥力模型——两个单位互相靠近时各自向垂直于连线方向偏移一点偏移量跟重叠深度成正比。实测下来单位群在移动时能自然形成松散队形既不会穿模也不会彻底堵死。当然军队在进攻阵型上的移动也可以用编队行为做得更漂亮但那个系统复杂度会再上一个台阶。我做了一个简化处理选中的多个单位移动到同一目标点时会自动在目标点周围按网格排开而不是全部挤在同一个中心坐标上。这个补丁让整队的“到达姿态”立刻自然了很多。4.3 AI 对手的经济崩溃与发呆循环AI 最难调的其实不是战斗力而是经济循环。初版 AI 经常出现这个问题攒够了 500 块钱就建精炼厂但精炼厂建完发现矿区太远采完一波要跑很久于是生产链就断了然后 AI 进入一个很呆的死循环——钱不够造兵资金逐渐枯竭。排查思路是先把 AI 的决策 log 全部打出来观察它每一帧到底在干什么决策、资源余额是多少。这一看就发现了AI 的“扩张”决策优先级太高资源稍微多一点就全部拿去建新建筑了导致军事生产被完全挤掉。修复办法是给 AI 加入“可负担判断阈值”——只有当余额超过某种建筑成本的 1.5 倍时才允许建造而不是刚好够了就动工这样预留了同时维持一支小型军队的空间。第二个修复是给 AI 加入经济优先级维持军队在先扩张基地在后只有当军队规模达标并且经济盈余时才会考虑多建一个矿场。调完之后AI 的暴兵节奏和资源增长明显更有层次感了。4.4 从报错到修复一次真实 Bug 的完整排查过程分享一个我最印象深刻的 bug游戏运行几分钟后单位开始随机消失内存占用肉眼可见地飙升。这个 bug 不是立刻出现的它“潜伏”了大概三分钟才爆发debug 起来特别痛苦。最初怀疑是内存泄漏检查 Action 里所有数组的 push 和 splice 都没发现问题。后来我用 Chrome Performance 录制了一段对局过程发现内存持续增长但代码逻辑里所有创建的对象好像都有对应的清理步骤。最终定位到罪魁祸首是事件监听器泄漏。单位在生产建筑里被创建时会绑定一个“创建完成”的事件监听器但当建筑被敌方摧毁时这个监听器没有被移除。当时整个游戏里其实同时存在很多已经消失的建筑残留的监听器仍在响应生产事件不断创建看不到的新单位这些单位占用了坐标但本身就崩了。这里我学到的最重要经验是不要相信 AI 自动生成的事件订阅/退订逻辑这种隐式连接的 bug 是最难通过 README 代码 review 察觉的。后来我在所有建筑和单位的 destroy 函数里统一加了解绑逻辑并写了一行注释提醒自己。另外一个排查技巧是在游戏里临时加一个 debug 面板实时显示当前单位数量、AI 数量、事件监听器数量一旦数值异常增长就知道问题大概出在哪个环节了。5. 开源以后社区反馈和这个项目还能做什么项目放到 GitHub 之后第一周的反馈超出了我的预期。Star 数涨得比我想象中快得多不少人 Fork 下来跑起来之后提了各式各样的 issue 和 PR。最让我高兴的是有一个开发者自己实现了一个“多人联机模式”的概念验证基于 WebSocket 做了一个简单的房间同步系统。虽然延迟很高、同步机制非常粗糙但它证明了这个项目代码的可扩展性是真实的——别人不需要了解全部细节就能在自己需要的方向上延展。这个项目未来的扩展空间其实非常大。我自己心里有几个已经想清楚的规划一是引入一套更丰富的兵种倾向和互相克制机制让战术纵深更强二是做一套简单的战役模式讲一个完整的故事流程而不只是一张张随机地图三是把整个 AI 策略层做成独立的可插拔模块让社区开发者可以提交自己的 AI 逻辑。如果你也想跑一个类似的项目我最后想给的一点核心建议是把 GPT 当结对编程伙伴而不是代码抄写员。它会给你一个能跑起来的骨架但真正让游戏“有魂”的细节——手感、节奏、平衡性、意外处理——这些飞跃还是需要你亲手一点点调出来的。用 GPT 做这种完整项目最大的乐趣也正在于此它帮你把天花板抬高了三倍而你自己的品味和判断力决定了最终能飞多高。