AI做的游戏能玩吗?SWE-Game基准测试的答案,以及用AI把游戏做到“真能玩”的实操方法
作者:很酷cat2026.11.14 09:19浏览量:1简介:让AI独立做一款游戏,它通常会先搭场景、放角色、做好移动和跳跃,然后故事就卡住了:尖刺看得见但踩上去没反应,通关画面能弹出来但玩家什么都没做就直接触发了。这不是段子,而是上海交大等机构的研究者在系统性测试AI编程能力时真实撞见的现象,结论被写进了 SWE-Game 这个基准:AI生成的游戏离“能玩”还差得远。本文拆解这个基准到底测了什么、为什么难测,并给出一套可落地的工程方法——用 [ERNIE 5.5 Flash Preview 在线体验](https://console.bce.baidu.com/qianfan/onlineTest/chat/ERNIE-5.5-Flash-Preview) 把AI的工作从“生成代码”推进到“生成可被验证的可玩性”。
一、先说结论:AI做游戏的瓶颈不在“写得出”,而在“跑得对”
如果你让AI写一个排序函数,跑一遍单元测试就知道对错。但游戏不一样,它活在玩家的操作里。
一个2D平台跳跃游戏里,“角色碰到尖刺应该死”这件事,没法靠阅读代码片段判断——你必须真的操纵角色走过去撞一下,看它是否死亡、是否扣血、是否回到检查点。研究团队把这个问题讲得很直白: 如果玩家看到通关画面就认为游戏做对了,那也可能是假象,因为游戏可能根本没要求玩家做任何操作,就直接弹出了胜利提示。
所以AI做游戏常见的失败模式,几乎都不是“编译不过”,而是这类语义级的空转:
| 失败表现 | 表面现象 | 真实原因 |
|---|---|---|
| 碰撞体缺失或层级错配 | 尖刺看得见,踩上去无反应 | Area2D/CollisionShape2D 未正确连接信号 |
| 胜利条件写反或恒真 | 一进关卡就弹通关 | 判定条件未与“收集/到达”状态绑定 |
| 状态机缺分支 | 跳跃后可二段跳、死亡后仍可操作 | 状态迁移条件不完整 |
| 数值与关卡不匹配 | 跳跃高度不足以通过既定缺口 | 关卡几何与角色参数未联合校验 |
| 假交互 | 按钮有反馈但无实际逻辑 | UI 信号未绑定业务函数 |
这些问题的共同点是: 只有运行时证据能证伪,静态阅读代码看不出来。
二、SWE-Game 到底测了什么
SWE-Game 的核心矛盾可以概括成一句话:怎么让评测既知道“这个游戏本来应该是什么样”,又能亲自“动手”去验证“它现在到底是什么样”。
为此团队没有凭空出题,而是先造了 41款真正能玩的参考游戏 ,横跨2D与3D,涵盖射击、平台跳跃、解谜、策略、模拟经营等 13种玩法类型 ,全部使用开源引擎 Godot 开发,美术上采用 Kenney 等现成素材包,并走了一套正规的开发流程。这批游戏的作用类似“标准答案”:它们既提供了明确的设计意图,也提供了可运行的参照实现。
在此之前,评测AI做游戏大致有两条路,各有明显短板:
- 让另一个大模型“看”游戏并打分。 相当于请一位美术老师远程批改他看不到实物的雕塑作业,只能看照片,判断力天然打折,且容易被“看起来像”的表象欺骗。
- 写死板的单元测试。 能判断某个函数返回值对不对,但抓不住“动态交互中的逻辑是否自洽”这种更接近游戏本质的问题。
同期的 WebGameBench(靠浏览器交互评测网页小游戏)、GameLogicBench(靠引擎内状态断言测试机制)各有侧重,但都没能把 设计意图 与 运行时证据 真正打通。SWE-Game 的价值就在于把这两端接了起来。
对开发者的直接启示是: AI做游戏的质量上限,取决于你有没有给它一套“可玩性验收标准”,以及一条能自动跑出运行时证据的回路。
三、把“可玩性”变成可执行的验收契约
想让AI(以及你自己)判断游戏是否做对,第一步不是写代码,而是把设计意图写成机器可读的契约。建议在动手前先产出一份 playability_contract.json,它同时是代码生成的输入和测试生成的输入。
{"game_id": "platformer_01","engine": "godot-4.3","genre": "2D平台跳跃","win_condition": "coins_collected == total_coins && player.touch_goal","fail_conditions": ["player.touch_spike", "player.position.y > 900"],"entities": [{"id": "player", "scene": "res://entities/player.tscn", "max_health": 3},{"id": "spike", "scene": "res://entities/spike.tscn", "damage": 1}],"acceptance_checks": [{"id": "AC-01", "desc": "碰到尖刺扣1点生命并进入短暂无敌", "type": "runtime_assert"},{"id": "AC-02", "desc": "未集齐金币时触碰终点不触发通关", "type": "runtime_assert"},{"id": "AC-03", "desc": "集齐金币后触碰终点弹出通关画面", "type": "runtime_assert"},{"id": "AC-04", "desc": "掉出关卡下边界后重生到检查点", "type": "runtime_assert"}]}
有了这份契约,“这游戏做得真不真”就从主观争论变成了 4 条可以自动跑的断言。
四、用 ERNIE 5.5 Flash Preview 搭一条“生成—自测—修复”闭环
ERNIE 5.5 Flash Preview 是文心系列基础模型 ERNIE 5.5 Flash 的预览版本,重点优化了编程、智能体、知识工作与深度研究等方向的能力,支持 1M tokens 长上下文 ,可结合工具调用与 Agent 工作流完成多步骤任务。它属于千帆平台提供的模型服务,平台侧同时提供模型调用、应用编排等工具链。
需要说明的是:它是文本模型,本身不运行 Godot、不渲染画面。真正跑起来需要本地 Godot 可执行文件或 CI 环境配合。它在这套流程里承担的是三件最耗人的事:
- 读懂整个项目。 1M 上下文意味着你可以把多个
.gd脚本、.tscn场景文本、日志一次性贴进去,让它做跨文件的一致性检查,而不是只看单个函数。 - 把契约翻译成测试代码。 从
acceptance_checks直接生成 Godot 无头测试脚本,覆盖碰撞、状态机、胜负判定。 - 读懂失败日志并定位根因。 把报错与复现步骤回灌,让它给出最小改动修复,而不是重写整个模块。
操作步骤
Step 1|生成设计规格与验收契约。 用一句话需求换取结构化规格,人工确认后再进入编码。
Step 2|生成代码骨架。 明确引擎版本、目录结构、命名规范,要求逐场景实现,避免一次性生成整个游戏。
Step 3|生成无头冒烟测试。 关键动作:让测试 模拟真实操作 (注入输入或直接驱动角色),而不是只调用函数。
Step 4|本地/CI 跑测。 命令示例:
godot --headless --path . -s res://tests/smoke_test.gd
Step 5|失败日志回灌修复。 把完整输出(含失败断言与堆栈)贴回模型,要求“最小改动 + 说明为什么之前会漏”。
Step 6|回归。 修复后重跑全部断言,防止修 A 坏 B。
可直接复制的 Prompt
Prompt 1:从需求到验收契约
你是资深游戏程序。请把下面的需求转成机器可读的验收契约,不要写实现代码。【游戏需求】2D平台跳跃,3条生命,尖刺扣1血并有1秒无敌,集齐5枚金币后触碰终点通关,掉出下边界重生到最近检查点。【引擎】Godot 4.3,GDScript。【输出要求】1. 输出 JSON,字段包含 game_id / engine / genre / win_condition / fail_conditions / entities / acceptance_checks;2. acceptance_checks 每条必须可在无头模式下自动判定,写明前置状态、操作动作、期望状态;3. 至少覆盖:碰撞伤害、无敌帧、胜负判定、重生逻辑、边界情况;4. 不要输出任何解释性文字,只输出 JSON。
Prompt 2:生成可运行的无头测试
基于以下验收契约,编写 Godot 4.3 无头测试脚本 tests/smoke_test.gd。【契约】{粘贴 playability_contract.json}【要求】1. extends SceneTree,通过 godot --headless -s 运行,全部通过打印 SMOKE TEST PASS 并以 0 退出,失败以 1 退出;2. 每条断言对应一个 AC 编号,失败时打印 AC 编号、期望与实际值;3. 必须驱动真实运行:实例化关卡场景、await physics_frame 让物理生效、通过设置角色位置或 Input.action_press 触发交互;4. 禁止用“检查变量是否被赋值”代替行为验证;5. 给出运行命令与依赖说明。
Prompt 3:失败日志定位与修复
以下是测试输出,请定位根因并修复。【失败输出】{粘贴完整日志}【相关代码】{粘贴 player.gd / spike.gd / level_01.gd}【要求】1. 先说明失败属于哪类问题(碰撞层配置 / 信号未连接 / 状态机缺分支 / 判定条件恒真);2. 给出最小改动 diff,不重写无关模块;3. 说明这次修复为什么不会破坏已有通过的 AC;4. 如怀疑是场景文件(.tscn)配置问题,指出需要检查的具体节点与属性。
测试脚本骨架示例
extends SceneTreeconst LEVEL := preload("res://levels/level_01.tscn")var failures: Array[String] = []func _initialize() -> void:_run.call_deferred()func _run() -> void:var level: Node = LEVEL.instantiate()root.add_child(level)await process_frameawait physics_framevar player = level.get_node("Player")var spike := level.get_node("Spikes/Spike01")# AC-01:真实驱动角色撞上尖刺,验证扣血而非仅检查变量var hp_before: int = player.healthplayer.global_position = spike.global_positionawait physics_frameawait physics_frame_check("AC-01", player.health == hp_before - 1,"health %d -> %d" % [hp_before, player.health])# AC-02:未集齐金币时触碰终点不应通关level.coins_collected = 2level.get_node("Goal").emit_signal("body_entered", player)await process_frame_check("AC-02", not level.is_won(), "is_won should be false")# AC-03:集齐金币后触碰终点应通关level.coins_collected = level.total_coinslevel.get_node("Goal").emit_signal("body_entered", player)await process_frame_check("AC-03", level.is_won(), "is_won should be true")if failures.is_empty():print("SMOKE TEST PASS")quit(0)else:for f in failures:printerr("FAIL " + f)printerr("SMOKE TEST FAILED (%d)" % failures.size())quit(1)func _check(id: String, ok: bool, detail: String) -> void:if ok:print("PASS " + id)else:failures.append("%s: %s" % [id, detail])
这段脚本的关键设计意图,正是 SWE-Game 强调的那一点: 先构造前置状态,再执行真实交互,最后断言运行时状态 ,而不是断言“某个变量看起来对”。
五、常见坑与排查建议
| 症状 | 优先检查 | 处理建议 |
|---|---|---|
| 无头模式行为与编辑器不一致 | 是否依赖渲染帧或视口尺寸 | 用 physics_frame 而非 process_frame 等待物理生效 |
| 测试通过但游戏仍不对 | 断言是否绕过了真实交互 | 改为注入输入或真实位移,禁止直接改内部变量后断言 |
| AI反复“修好又坏” | 是否缺少回归集合 | 把全部 AC 固化进 CI,每次提交全量跑 |
| 3D 场景判定漂移 | 碰撞体尺寸与角色参数不匹配 | 把角色参数与关卡几何一起交给模型做联合校验 |
| 生成代码风格不一致 | 缺少项目约定 | 在 Prompt 中固定目录结构、命名规范、引擎版本 |
六、进阶:把这条回路交给智能体
当游戏规模变大,人工搬运日志会成为瓶颈。可以把整个循环交给 Agent 工作流:读取契约 → 生成/修改代码 → 调用本地 Godot 无头执行 → 解析输出 → 决定修复或结束 → 提交回归报告。ERNIE 5.5 Flash Preview 在编程、工具调用与多步骤任务上的优化,正适合承担这类“规划 + 调用 + 判断”的角色;执行环节仍需由本地环境或 CI 完成。
落地时建议保留三条护栏: 契约先行 (不允许无验收标准就生成)、 证据优先 (只接受运行时断言结果作为通过依据)、 最小改动 (禁止用重写掩盖根因)。
七、关键步骤回顾
- 承认瓶颈:AI做游戏的失败大多发生在运行时语义层,不是语法层。
- 参考 SWE-Game 的思路:为每款游戏准备明确的设计意图 + 可运行的参照实现。
- 把设计意图写成
playability_contract.json,让验收标准可执行。 - 用无头模式跑真实交互测试,断言运行时状态而非变量赋值。
- 失败日志回灌模型定位根因,全量回归防止反复。
- 规模上来后交给 Agent 工作流,并保留契约、证据、最小改动三条护栏。
想验证这套方法,可以先在 ERNIE 5.5 Flash Preview 在线体验 里粘贴你的游戏需求和验收契约,看看它生成的测试用例是否真的在“驱动角色玩”,而不是在“检查变量”。开发者也可以前往 百度智能云千帆模型详情页 了解模型能力、上下文规格与接入方式,再把测试回路接到自己的 Godot 项目与 CI 上。

登录后可评论,请前往 登录 或 注册