
“让我用 Godot 做一个雪地生存游戏。”如果你看过这类 prompt 在聊天框里跑出来的结果大概能猜到会发生什么AI 很兴奋地回你一大段代码节点结构写在注释里GDScript 塞在一个代码块里还顺手帮你规划了 UI、背包、敌人 AI、音效、存档。看起来像一个完整方案复制进去却根本跑不动。问题不是出在 AI 的能力而是出在提问方式。你让 AI 一口吃成胖子它就只能给你一个想象中的完整游戏而不是一个能一步步验证的工程。我后来换了一种做法不再要求一个 AI 从头到尾做完游戏而是把流程拆开让 4 个 AI 分别负责不同环节每个 AI 只做一件足够小、边界足够清楚的事。最后用这个方式做出了一个能跑的雪地生存游戏 Demo。这篇文章不聊“AI 能不能替代程序员”这种宏大问题只聊一件很实际的事当你想用 AI 辅助做一款 Godot 游戏时怎么拆任务、怎么定边界、怎么验证每一小步才能真的把游戏做出来。1. 先承认一个事实AI 做不出“完整游戏”但能做好“每个小块”很多独立游戏开发者以为AI 编程的价值在于“我什么都不用懂把需求讲清楚就能得到一款游戏”。现实是游戏本身是一个系统性工程有场景、逻辑、资源、配置、输入、状态机、UI、音效、打包和跨平台问题。让 AI 在一个对话里同时兼顾这些东西它很快会顾此失彼。这里的原因并不玄妙。游戏代码不是一段连续的长文本而是一堆互相依赖的小文件的集合。玩家移动脚本需要读输入敌人 AI 需要找路径UI 要监听玩家状态背包系统要跟场景里的物品打交道。每一个文件都有自己要解决的问题但文件之间又有边界。AI 在单个上下文里能维护的信息量有限当它试图“一人分饰多角”时最常见的结果是生成了十几个脚本但彼此之间引用关系错乱。场景需要的节点路径写错运行时报一堆空引用。设计文档写得很好但代码根本没法落地。有些脚本是完整的有些只留了pass和 TODO把上下文给 AI 看它自己都忘了还欠着什么。所以我的第一个建议是放弃“一次生成整个游戏”的幻想。不是 AI 不行而是这个任务结构本身不适合单次生成。反过来如果你把一个游戏拆成“玩法规则”、“场景骨架”、“逻辑脚本”、“调试打磨”四块每一块单独交给一个 AI 去做每一块的复杂度就会降到可控范围内。这就像组织一个团队开发。你不会让一个人同时负责策划、模型、程序和测试你会让每个角色各管一段通过接口对接。AI 协作也是同一个道理。1.1 四个象限把游戏任务拆成 AI 能独立处理的单元我在这次雪地生存游戏里把整个制作流程拆成了四个象限每个象限对应一个 AI 服务或一次独立对话。这里用“象限”而不是“步骤”是因为它们之间有依赖关系不是简单的前后顺序而是一层一层往下喂。玩法设计象限负责定义“这个游戏到底怎么玩”。包括规则、胜利条件、失败条件、核心循环。它输出的不是代码而是文字描述、流程清单、状态清单。场景架构象限负责定义“Godot 项目里节点树长什么样”。玩家节点挂在哪个父节点下物品生成器放在哪UI 画布怎么组织。输出的是一份场景目录、节点路径和脚本骨架。逻辑实现象限负责把每个脚本填充成能跑的代码。它接收场景架构的输出按文件实现具体功能比如玩家移动、物品拾取、温度下降、篝火回血。测试与打磨象限负责根据错误日志、运行结果和手感反馈提出修复建议和参数调整。它不负责写新功能只处理“哪里坏了、哪里不顺手、哪里性能差”。这四个象限对应 4 个 AI但你不需要同时打开四个窗口。实际流程是串行的A 象限的输出作为 B 象限的输入B 象限的输出再交给 C 象限最后 D 象限回来调整。每一层都限制在各自的能力圈里不会出现一个 AI 从玩法设计一路写到打包配置的情况。你可能会问为什么是四个不是两个也不是八个两个的话设计和实现会混在一起八个的话任务之间的接口沟通成本又会超过收益。四个是一个很自然的折中正好对应游戏开发里的“概念设计—场景搭建—逻辑编码—测试打磨”四个阶段每个阶段的任务边界足够清楚AI 之间不需要太多来回。1.2 每个 AI 都需要一份“边界清晰的输入”而不是一句大需求跟 AI 协作时最忌惮的是“帮我做一款雪地生存游戏”这种开放需求。它不是不能做而是它做完之后你不知道怎么验证。开放需求对应着开放输出开放输出很难检查对错。我在实际流程里会给第一个 AI 一份更聚焦的 prompt目标是让它输出可验证的规则而不是代码。比如我会写你是一位独立游戏策划。请为一款 2D 雪地生存游戏设计核心玩法。要求单局时长不超过 5 分钟。玩家需要收集木材、保持体温、点燃篝火。角色有体温和生命值两条状态。敌人只有一种风雪强度而不是怪物。输出内容只包含玩法规则、流程步骤、状态清单、胜负条件。这个 prompt 和“帮我做雪地生存游戏”最大的区别在于它限定了输出格式、玩法边界和验证标准。AI 返回的不再是一大坨五花八门的方案而是一份可以检查的规则表。接下来第二个 AI 就能基于规则表而不是基于泛泛的描述去设计场景节点。所以与其问“怎么让 AI 做游戏”不如先问自己一句我能把游戏需求拆成几个可验证的小交付物2. 四个 AI 的分工本质是四个工序不是四个“神灯”很多人对 AI 协作的理解是“我同时在用好几个 AI看谁生成的代码更好”这不是协作这是货比三家。真正的协作是流水线式每个 AI 的输出会成为下一个 AI 的输入上一个角色的交付物就是下一个角色的需求文档。我在这个雪地生存游戏里四个 AI 的分工大致是这样。2.1 第一个 AI玩法规则说明书第一个 AI 做的是策划工作。它的输入是“2D 雪地生存游戏”这个初始需求输出是一份简短的玩法规则。注意这里我刻意不让它写任何代码甚至不讨论 Godot 技术选型只讨论玩法本身。这步的价值在于先把“做出一个游戏”这个大目标转化成“实现一套可以跑的规则”这个小目标。比如规则表里会写玩家初始体温 37 度。温度会随时间下降。木材堆会随机刷新在雪地地图上。按下交互键收集木材。在篝火附近按交互键添加木材篝火燃烧时温度恢复。体温降到 30 度以下开始扣血。血量为零则游戏结束。每局计时 3 分钟看玩家能维持多久。这些规则不需要 AI 会“编程”它只需会“梳理”。但它决定了后面每一步怎么写。如果把这一步省略直接让 AI 写玩家移动、温度系统、木材采集它也能写但写出来的功能大概率彼此不协调。比如温度下降速度、木材刷新频率、篝火燃烧时长之间如果没有一份规则约束AI 只会随便填参数。最后手感会非常烂温度掉得太快、木材太稀疏、篝火烧几秒就灭各种想当然的数值堆出一个没法玩的游戏。2.2 第二个 AIGodot 场景与脚本骨架第二个 AI 拿到的输入是第一份规则说明书。它要输出的是在 Godot 4 项目里先建哪些节点、脚本文件如何组织、资源放在什么目录下。理想情况下这个 AI 会给你类似这样的场景骨架res:// ├── scenes/ │ ├── main.tscn │ ├── player/ │ │ └── player.tscn │ ├── world/ │ │ ├── snow_tilemap.tscn │ │ └── wood_spawner.tscn │ └── ui/ │ └── hud.tscn ├── scripts/ │ ├── player.gd │ ├── main.gd │ ├── temperature.gd │ └── wood_pickup.gd ├── assets/ │ ├── sprites/ │ └── audio/ └── project.godot需要说明的是AI 生成的骨架结构不会每次都这么规范通常需要你手动调整目录名和命名风格。但重要的是这一步会让“怎么做”有了一个具体落点。后面第三个 AI 填充代码时不需要再猜测路径和文件名直接照着骨架写就行。这一步还能减少一个非常典型的错误节点路径写错。如果由同一个 AI 先生成场景结构、再生成引用路径的代码出错的概率会小很多如果场景结构在需求阶段根本没有确定第三个 AI 很容易写出不存在的节点路径。2.3 第三个 AI逐个脚本实现功能第三个 AI 进入编码环节。它接收场景骨架按文件逐个实现。我一般会每个脚本单独开一次对话而不是让一个 AI 把 player.gd、temperature.gd、wood_pickup.gd 全写了。为什么分开因为单个脚本的上下文更短AI 更容易写出自洽的逻辑。比如玩家移动脚本只需要关心输入和速度温度脚本只需要关心数值变化和外部事件木材拾取只需要关心交互触发。这些脚本如果放在同一个对话里AI 会不停地在脚本之间“跳来跳去”最后往往出现互相调用但函数名不一致的问题。用 AI 写代码时你要把每个脚本当成一个“组件”来审视输入是什么输出是什么依赖哪些外部信号。不用写多复杂但边界要清楚。第三个 AI 生成完后我会先把所有.gd文件放进项目里看看 Godot 是否能解析、有没有明显的语法错误。只有能解析通过才会进入下一步。这一步也是工作量的主体。以雪地生存游戏为例核心代码其实不复杂不外乎玩家移动含雪地减速。温度随时间下降。交互拾取木材。篝火燃烧回温。HUD 显示数值。游戏结束条件。每段代码单独验证而不是等全部写完再一起跑。出一个改一个效率反而更高。2.4 第四个 AI根据报错和手感反向修代码第四个 AI 的地位最容易被低估。它不是来加新功能的而是负责“让游戏跑起来并且能玩”。跑起来和能玩是两回事。跑起来只需要没有报错能玩需要数值平衡、反馈时机、操作手感都合理。第三个 AI 生成的代码数值几乎一定很粗糙温度掉太快、篝火回血过猛、木材刷新频率不匹配这些都要在测试阶段靠第四个 AI 调整。我一般会把错误信息或手感问题整理成描述发给第四个 AI让它给出修复方案。比如玩家在移动时会出现抖动像是一直在重复碰撞检测请问在 Godot 4 里怎么排除或者体温在两个节点之间同步出现了延迟HUD 更新比内部数值慢一帧应该怎么改这个阶段 AI 的价值不是“写代码”而是“定位问题 给出修改方案”。它能把一个小问题解释得很清楚让你明白是信号没连接上、数值没 round 还是节点路径错了。对初学者来说这是最实用的一个 AI。3. 用这套流程做雪地生存游戏最小可以长这样理论说完了看一下实际项目。这个雪地生存游戏的 Demo 很小核心玩法只围绕“温度”展开玩家在雪地里移动会越来越冷必须捡木材、点篝火维持体温。不是 3A也不是横版卷轴就是一个可运行的 2D 小游戏。下面这个示例代码是 Combine 简化版本用于说明第三象限 AI 生成的最终效果。实际 AI 生成结果会更啰嗦可能需要你手动删一些无用注释和冗余分支。3.1 环境准备与前置条件我使用的是 Godot 4.x 版本。如果你用的是 Godot 3.x部分 API 名称和信号系统需要自行对照调整。AI 生成代码时我通常会在 prompt 里注明确切的 Godot 版本因为 GDScript 在 3.x 和 4.x 之间有些函数名不一样比如move_and_slide的调用方式、get_input的处理逻辑都有变化。环境准备其实很简单安装 Godot 4.x。新建一个空项目。用 AI 生成场景骨架时先创建好对应的目录结构。把 AI 生成的.tscn和.gd文件放入对应目录。这里有一个很实用的经验小项目不用一开始就追求完美的目录结构但一定要保证scenes/和scripts/是分开的。否则后续让 AI 修 bug 时它很可能因为找不到脚本文件而乱猜路径。3.2 玩家移动脚本AI 生成后我改了两处玩家移动是一个很典型的 AI 生成结果。如果我直接让 AI 写它会生成一个包含跳跃、冲刺、动画切换、碰撞检测的大脚本。但我的雪地生存游戏只需要 2D 平面移动甚至不需要跳跃。所以我会在 prompt 里主动收紧需求。AI 产出的玩家移动脚本通常长这样extends CharacterBody2D export var speed : 200.0 export var snow_slow_factor : 0.6 func _physics_process(_delta): var direction : Vector2( Input.get_axis(ui_left, ui_right), Input.get_axis(ui_up, ui_down) ).normalized() var current_speed speed if is_on_snow(): current_speed * snow_slow_factor velocity direction * current_speed move_and_slide()但 AI 生成的版本不会这么干净它会自动添加很多“它认为你需要”的东西比如跳舞的相机跟随、动画判断、甚至攻击逻辑。我一般会要求它“只保留移动和地面减速删除其他一切功能”然后再手动删掉注释里的大段解释。这里出现了一个重要经验AI 写代码越多你手动删得越多。与其让它生成一个大而全的脚本不如限制它只做一件事。脚本越短出 bug 时越容易把整个脚本贴给 AI 分析。3.3 温度模块与篝火回血通过信号解耦温度模块是冬季生存的核心。一开始我想让温度模块直接耦合到玩家脚本里每帧检查温度并扣血。后来发现这种方式一旦出问题很难定位是移动的问题还是温度的问题。我改成了分离式设计温度由全局数据管理玩家只负责接收“当前温度值”的传入HUD 单独监听温度变化。这听起来像是一个工程上的过度设计但对小型 AI 协作项目来说反而更不容易翻车。因为每个模块只对一类输入负责AI 生成代码时思路更清晰。extends Node signal temperature_changed(new_value) var current_temperature : 37.0 var temperature_decrease_per_second : 0.3 var near_fire : false func _process(delta): if near_fire: current_temperature min(current_temperature 5.0 * delta, 37.0) else: current_temperature - temperature_decrease_per_second * delta if current_temperature 30.0: Global.health - 10 * delta if Global.health 0: get_tree().change_scene_to_file(res://scenes/game_over.tscn) temperature_changed.emit(current_temperature)这个脚本本身并不复杂但 AI 在生成时经常会把near_fire这个状态搞乱比如把它写成局部变量每帧重置。如果你发现玩家站在篝火边体温也不恢复先检查这类状态变量是不是被写成了局部变量。3.4 木材拾取Area2D 和交互按钮木材拾取我是用Area2D 输入检测实现的。玩家靠近木材时木材节点发信号玩家按下交互键木材被收集并计入背包。这一步 AI 生成时最容易出的问题是信号连接路径写错。Godot 的场景信号可以在编辑器里手动连接也可以代码连接。AI 默认代码连接但它不知道你的节点路径。解决方式很简单你写清楚wood_pickup.tscn的外部节点路径或者干脆让 AI 在_ready()里用get_parent()拿玩家节点而不是硬编码绝对路径。extends Area2D func _ready(): body_entered.connect(_on_body_entered) body_exited.connect(_on_body_exited) var can_pick : false var picked : false func _input(event): if event.is_action_pressed(interact) and can_pick and not picked: Global.wood_count 1 picked true queue_free() func _on_body_entered(body): if body.is_in_group(player): can_pick true func _on_body_exited(body): if body.is_in_group(player): can_pick false这段代码的问题在于_input会在任何输入都检测一次即使玩家离开木材还在监听。但在小 Demo 里完全够用。如果 AI 生成的版本里没有分组判断而是直接判断body.name Player性能上没有区别但可维护性差一些。我会主动要求 AI 使用is_in_group这样改名后逻辑不受影响。4. AI 生成 Godot 代码最容易翻车的几个坑AI 能生成代码不代表它生成的代码能直接用于真实项目。在实际跑完雪地生存游戏之后我整理了一些高频坑基本都是 Godot 开发里最常见的。这些坑不是 AI 独有但 AI 生成会放大它们。4.1 2D 人物走路模糊、锯齿严重如果你用 AI 生成一个快速原型导入的默认图片是像素画风格或者自带缩放很容易出现走路模糊和锯齿。这不是代码逻辑问题而是 Godot 的默认纹理过滤设置不符合像素风需求。排查路径右键导入的图片资源在 Import 面板中把 Filter 改为 Nearest。或者在项目设置中搜索texture filter把默认过滤改成Nearest。如果相机跟随玩家检查相机zoom是否使用了小数缩放。像素风游戏建议用整数缩放避免像素点被拉伸成模糊块。打开项目设置中的render/2d/snap/snap_2d_transforms_to_pixel和snap_2d_vertices_to_pixel能在一定程度上减少抖动。如果你看到的是“走路时画面整个轻微抖动”多半是相机平滑跟随和像素对齐打架。禁用相机平滑或关闭像素对齐二选一。4.2 用 queue_free() 而不是 free()AI 生成的代码里很容易出现free()或queue_free()混用甚至直接调用node.free()后还继续访问这个节点。Godot 中free()会立即销毁节点但如果有其他引用还指向它最后就会得到空引用错误queue_free()是在当前帧结束后安全移除节点。我建议不管 AI 生成的是什么一律把销毁节点的方式改成queue_free()。如果你想确保节点移除后不再被访问可以花钱set_process(false)或从父节点移除它再销毁。这个坑在“拾取木材后”最容易暴露。AI 生成的代码里经常是先queue_free()然后又访问木柴的全局坐标。这不是大问题但会导致间歇性报错尤其在批量生成多个木材节点时。4.3 Dictionary 的键类型问题Godot 的Dictionary不像强类型语言那样严格限制键类型所以 AI 很容易生成这样的代码var inventory : {} inventory[health] 100这会运行但如果你后续做存档和读取就会遇到 JSON 序列化时键名大小写、类型不一致等问题。AI 生成代码时我通常会在 prompt 里加一句“使用内置类型Dictionary中的键统一使用StringName”。这在复杂项目里能避免非常隐形的坑。另外AI 从 Python 迁移到 GDScript 时写循环遍历字典往往会有问题比如写着for key, value in dict.items()Godot 4 中不支持这种方法而应该写for key in dict: value dict[key]。如果没有注意运行时直接报错。4.4 节点删除后仍被引用AI 生成的代码里经常出现“先删节点后面又用变量名去访问被删节点的属性”。比如木材被拾取后删除了但如果其他脚本里还引用wood.position就会报错。排查时先看栈信息是否指向一个已经被queue_free()的节点。如果频繁出现考虑让木材节点只禁用碰撞体而不是删除或者通过信号让其他对象在删除前先解除引用。4.5 版本管理AI 改你代码前先提交一次这点特别重要。AI 改代码很像“不请自来的队友”它可能把一整段代码重写导致之前能跑的东西突然崩溃。如果没有版本管理你根本没法知道改动前后发生了什么。建议从第一天就用 Git 管理项目。Godot 项目通常可以安装 git 插件简化操作。AI 每次生成代码前先 commit 一次AI 写完后对比 diff再决定保留还是丢弃。这个过程不仅防止 AI 破坏项目也能帮助自己理解 AI 到底改了什么。4.6 打包后资源加载问题如果你打算把游戏导出到 Android 或 WebAI 生成的代码通常不关心资源加载路径而真实项目里会碰到APK加载.pck文件、资源路径大小写、Android 权限等问题。开发阶段在编辑器里跑得通不代表导出后也能跑。所以最稳妥的做法是先专注于编辑器内能跑通再考虑导出。导出需求出现时把它单独作为一项任务丢给 AI 处理不要在开发中期让 AI 一边写玩法一边处理打包配置。5. AI 协作的边界它不做判断但它能节省你大量验证时间用 4 个 AI 分步协作做完这个小游戏后最直接的感受是效率提升不一定体现在“几小时写出代码”而是体现在“几小时定位问题、确认边界、避免大量无效方向”。AI 不是创意来源它不会告诉你“雪地生存比地下城更合适”它也不会帮你判断你的玩家到底喜欢快速动作还是慢节奏生存。这类决策只能由你来定。AI 适合做的是在你确定方向之后帮你快速生成候选实现、快速跑试验、快速排错。如果你把 4 个 AI 分步协作当成一个固定流程我建议你按“最小可验证”的原则推进每个阶段只输出一个可验证的成果确认后再进入下一阶段。不要图快一口气跑完四步因为前一步如果错了后三步全都会在错误的地基上打转。这套方法的真正价值不是让你拿到一个“AI 生成好玩的游戏”而是把“做一个游戏”这件容易被 AI 一口吃掉的大任务拆成几个可控制、可调试、可迭代的小步骤。AI 每次只吃一小口你才有力气消化和修正最终做成一个能跑、能玩、能不断改进的东西。如果下次你还想用 AI 做游戏先别急着写 prompt。先写一张纸这个游戏的核心循环是什么最少的场景和脚本有哪些每一步怎么验证。把这张纸交给 AI你会发现它比你以为的靠谱得多。