1. 三款模型同台做3D游戏,我为什么选这个题
最近这段时间,AI编程助手这个赛道热闹得有点不像话。Step 5 Preview、DeepSeek V4 Pro、GLM5.3 这几个名字轮番出现在各种讨论里,群里、社区里、甚至我那个做客服主管的朋友都在问“到底哪个写代码更靠谱”。光看跑分和榜单其实没什么意思,真正能拉开差距的,是让它们干同一件有明确验收标准的活儿。3D游戏恰好就是这么一个活儿——它同时考验数学功底、图形学理解、代码组织能力,还有对游戏循环这种实时系统的把控。任何一个环节掉链子,跑起来就是黑屏或者穿模,藏都藏不住。
我这次做的事情很直接:给三个模型同一个需求,让它们各自从零写一个能在浏览器里跑起来的小型3D游戏,然后我把三份代码都实际跑一遍,记录下从生成到调试再到最终可玩的完整过程。选3D游戏而不是待办清单或者博客系统,是因为后者太容易“看起来对”——语法没错、逻辑通顺,但3D游戏不行,向量算错一个符号,摄像机就飞到天外去了。这种硬性约束让对比变得有意义。
这篇文章适合谁看?如果你正在纠结日常开发该把哪个模型放进工作流,或者你是个刚接触AI辅助编程的开发者想知道这些工具的真实水平边界,再或者你单纯好奇“AI到底能不能写游戏”,那接下来的内容应该能给你一些一手参考。我会把每个模型的输出特点、踩到的坑、以及我最后怎么把它们跑起来的过程都摊开讲,不吹不黑,只说我实际看到的东西。
2. 三个模型的脾气秉性:从第一轮生成看差异
2.1 需求描述与我的预期管理
我给三个模型的提示词是完全一样的,这里先把它贴出来,后面所有分析都基于这个输入:
用 Three.js 写一个单文件 HTML 的 3D 小游戏。要求:一个 20x20 的平面地面,玩家控制一个方块在地面上移动,方向键控制前后左右,摄像机跟随玩家。地面上随机散布 10 个金色小球,玩家碰到小球就吃掉,得分加一。全部吃完显示“通关”。代码要能直接保存成 html 文件双击打开就能玩。
这个需求我故意设计得“刚好够用”:Three.js 是CDN引入,不需要构建工具;单文件意味着模型必须自己组织好代码结构;碰撞检测用简单的距离判断就行,不需要物理引擎。这样能把注意力集中在模型对3D空间的理解和代码完整性上,而不是被工程配置干扰。
我预期的理想输出应该包含:场景初始化、透视相机、渲染循环、键盘事件监听、玩家移动逻辑、球体生成、碰撞检测、得分UI、通关判定。大概150到250行代码,结构清晰,变量命名合理。
2.2 Step 5 Preview:结构最规整,但有个隐蔽的坑
Step 5 Preview 给我的第一印象是“像个科班出身的程序员”。它输出的代码有清晰的注释分区,变量命名用了playerMesh、collectibles、moveDirection这种一看就懂的名字。场景初始化部分它甚至主动加了renderer.setPixelRatio(window.devicePixelRatio)和窗口 resize 监听,这两个细节很多模型会漏掉,但实际体验差别很大——不加的话在高分屏上画面会糊,窗口拉伸会变形。
它的移动逻辑用的是速度向量累加的方式,每帧根据按键状态计算velocity,然后position.add(velocity)。这种写法比直接改 position 要规范,帧率无关性更好。碰撞检测它用了distanceTo方法,判断距离小于某个阈值就触发收集,逻辑没问题。
但这里有个坑:它把玩家移动的边界限制写成了硬编码的if (position.x > 10) position.x = 10这种形式,而地面是20x20,坐标范围应该是 -10 到 10。它只限制了正方向,负方向没管。结果就是玩家可以往负方向一直走,走出地面掉进虚空。这个bug在快速测试时很容易被忽略,因为大部分人测试时习惯先按右和下。
2.3 DeepSeek V4 Pro:代码最紧凑,但可读性打了折扣
DeepSeek V4 Pro 的输出明显更“老练”,代码行数比 Step 5 Preview 少了大概三分之一。它用了很多链式调用和简写,比如把几何体创建和材质设置合并成一行,用数组解构来批量创建球体。从工程角度这很高效,但对于要阅读和修改代码的人来说,理解成本上去了。
它的一个亮点是主动加了简单的光照——一个环境光加一个平行光。Step 5 Preview 只用了基础材质,球体看起来是平的,DeepSeek 加了光照后球体有了明暗变化,视觉上更像“3D”。这个细节说明它对“3D游戏”的理解不只是功能实现,还考虑了观感。
问题出在键盘事件处理上。它用了keydown和keyup配合一个keys对象来记录按键状态,这本身是对的。但它没有处理keydown的重复触发问题——按住方向键时浏览器会连续触发keydown,虽然它的逻辑是设置布尔值所以不会累积,但它在keydown里调用了event.preventDefault(),这会导致页面无法用方向键滚动。对于全屏游戏来说无所谓,但如果页面有其他内容就会很别扭。更关键的是,它漏掉了keyup在窗口失焦时的清理,切出去再切回来,按键状态会卡住,玩家会一直往一个方向跑。
2.4 GLM5.3:注释最详细,但有个数学错误
GLM5.3 的输出是三个里面注释最多的,几乎每个函数上面都有说明,甚至写了“// 计算玩家与球体的欧几里得距离”这种。对于学习目的来说这很友好,你能清楚看到它的思路。
它的移动逻辑用了三角函数来计算方向,把按键映射到角度,然后sin和cos算位移。这个思路本身没问题,但它把角度和弧度的转换搞混了——Math.sin接受的是弧度,它传进去的是角度值。结果就是移动方向完全不对,按上键往斜上方跑。这个bug很典型,属于“看起来很有道理但一跑就露馅”的类型。
另外它的碰撞检测阈值设成了0.5,而玩家方块和球体的尺寸加起来实际接触距离应该是1.0左右。阈值太小导致必须非常精确地重叠才能触发收集,玩起来很别扭,感觉“明明碰到了却没吃到”。
2.5 第一轮对比小结
| 维度 | Step 5 Preview | DeepSeek V4 Pro | GLM5.3 |
|---|---|---|---|
| 代码行数 | 约220行 | 约150行 | 约260行 |
| 结构清晰度 | 高 | 中 | 高 |
| 注释详细度 | 中 | 低 | 高 |
| 光照处理 | 无 | 有 | 无 |
| 主要问题 | 边界限制不完整 | 按键状态清理缺失 | 角度弧度混淆 |
| 首次可运行 | 是(但有边界bug) | 是(但有卡键bug) | 否(移动方向错误) |
这个结果其实挺有意思:三个模型都能生成“看起来能跑”的代码,但都有各自的问题。没有一个是完美的,区别在于问题的隐蔽程度和修复难度。
3. 把代码跑起来:我的调试实录
3.1 测试环境与验收标准
我的测试环境很普通:一台装了Chrome的笔记本,代码保存成.html文件后直接双击打开。没有用任何本地服务器,因为需求里明确说了“双击打开就能玩”,这是对模型输出完整性的一个硬性检验——如果它依赖了模块导入或者外部文件,双击就会失败。
验收标准我定了四条:第一,页面打开后能看到地面和玩家方块;第二,方向键能控制移动且方向正确;第三,碰到球体后球体消失且得分增加;第四,吃完所有球体后显示通关提示。四条全过才算“可玩”。
3.2 Step 5 Preview 的边界修复
Step 5 Preview 的代码打开后画面正常,地面和方块都在,方向键也能动。我按着左键一直走,方块果然走出了地面边缘,然后画面里就只剩一个孤零零的方块悬在背景色里。问题确认。
修复很简单,把边界判断改成对称的:
// 修复前 if (player.position.x > 10) player.position.x = 10; if (player.position.z > 10) player.position.z = 10; // 修复后 player.position.x = Math.max(-10, Math.min(10, player.position.x)); player.position.z = Math.max(-10, Math.min(10, player.position.z));用Math.max和Math.min组合比写四个if更简洁,也不容易漏。改完之后再测,四个方向走到边缘都会被挡住,正常。
这里有个经验:AI生成的边界限制代码经常只写一半,因为训练数据里很多示例就是演示性质的,不会考虑完整边界。你拿到代码后第一件事就是往四个方向都走一遍,看看有没有漏的。
3.3 DeepSeek V4 Pro 的按键状态修复
DeepSeek 的代码打开后画面明显更好看,球体有立体感。移动也正常,但当我按住上键然后按 Alt+Tab 切出去再切回来,方块就一直在往上跑,按其他键也没用。这就是典型的按键状态卡死。
修复方法是监听窗口失焦事件,清空按键状态:
window.addEventListener('blur', () => { keys = {}; });另外它那个preventDefault我保留了下来,因为游戏确实不需要页面滚动。但如果你要把这段代码嵌到有滚动内容的页面里,记得去掉或者加条件判断。
还有一个细节:DeepSeek 的球体生成用了Array.from({length: 10}, ...)这种写法,很紧凑,但球体位置是纯随机的,有可能生成在玩家初始位置附近导致一开局就吃到好几个,也有可能两个球体重叠。实际玩的时候体验不太稳定。我后来手动加了个最小距离判断,让球体之间至少隔开2个单位,这样分布更均匀。
3.4 GLM5.3 的角度弧度修复
GLM5.3 的代码打开后画面正常,但按上键方块往右上方跑,按右键往右下方跑,完全乱了。定位到移动逻辑:
// 问题代码 const angle = getAngleFromKeys(); // 返回角度值,如90 player.position.x += Math.sin(angle) * speed; player.position.z += Math.cos(angle) * speed;Math.sin和Math.cos要的是弧度,90度对应的弧度是Math.PI / 2。它直接传了90进去,Math.sin(90)约等于0.894,Math.cos(90)约等于-0.448,算出来的方向当然是歪的。
修复就是加一个转换:
const angleRad = angle * Math.PI / 180; player.position.x += Math.sin(angleRad) * speed; player.position.z += Math.cos(angleRad) * speed;改完之后方向就对了。但还有个小问题:它的移动没有做对角线归一化。同时按上和右时,两个方向的位移会叠加,实际速度是单方向的1.414倍。虽然不影响功能,但手感上会感觉斜着走更快。要修的话就在计算完位移后除以模长,或者简单点,判断如果两个方向同时按下就把速度乘以0.707。
碰撞阈值我也从0.5改到了1.0,改完之后收集手感正常了。
3.5 三份代码的最终可玩性对比
修完bug之后,三个版本都能完整通关。但玩起来的感受有差异:
Step 5 Preview 的版本最“朴素”,没有光照,球体是纯色圆片的感觉,但移动和收集都很跟手,帧率稳定。DeepSeek 的版本视觉最好,球体有立体感,但球体分布随机性太强,有时候要绕很远找最后一个球。GLM5.3 的版本注释最多,适合拿来学习,但初始代码的问题也最多,修复花了最长时间。
如果让我选一个作为“开箱即用”的起点,我会选 Step 5 Preview,因为它的bug最少且最容易修。DeepSeek 适合对视觉效果有要求且愿意自己调整参数的场景。GLM5.3 更适合教学或者需要详细注释的场合。
4. 从3D游戏这个任务看三个模型的真实能力边界
4.1 空间数学能力:谁真正理解三维坐标
3D游戏最核心的门槛是空间数学。这次测试里,三个模型都表现出了对三维坐标的基本理解——都知道用x和z表示地面平面,y表示高度。但在具体运算上差异明显。
Step 5 Preview 的移动逻辑用的是向量累加,这是最稳妥的做法,不涉及三角函数,出错概率最低。DeepSeek 也用了类似的方式,但它把速度直接写成了固定值,没有考虑帧率波动。GLM5.3 尝试用三角函数做方向计算,思路更“数学化”,但恰恰在角度弧度转换上栽了跟头。
这反映出一个规律:模型在训练数据里见过大量“用三角函数算方向”的代码,但很多示例代码本身就没有严格区分角度和弧度,模型学到了形式却没学到精度。相比之下,向量累加这种“笨办法”反而更可靠。
4.2 代码完整性:谁更接近“能直接交付”
“双击就能玩”这个要求其实很苛刻,它排除了所有需要构建步骤的方案。三个模型都正确使用了CDN引入Three.js,没有出现import语句导致跨域失败的情况。这说明它们对“单文件HTML”这个约束的理解是到位的。
但在细节完整性上,Step 5 Preview 加了窗口resize处理,DeepSeek 加了光照,GLM5.3 加了详细注释。每个模型选择补全的“额外细节”不同,这跟它们的训练偏好有关。没有哪个是全面占优的,你需要根据自己项目的实际需求去挑。
4.3 调试友好度:出问题后谁更容易修
从调试角度,Step 5 Preview 的代码最好修,因为结构清晰、变量名直观,你一眼就能定位到问题在哪。DeepSeek 的代码紧凑,修的时候需要先花时间理解它的简写逻辑。GLM5.3 的注释帮了忙,但它的数学错误需要你本身懂角度弧度才能快速定位。
这里有个实用建议:如果你对3D数学不是特别熟,优先选代码风格直白的模型输出。紧凑的代码看起来高级,但调试成本高。注释多的代码适合学习,但如果你赶时间,注释反而会干扰你找bug的速度。
4.4 一个容易被忽略的点:得分UI和通关判定
三个模型都实现了得分显示和通关判定,但实现方式不同。Step 5 Preview 用了DOM元素来显示得分,每帧更新innerHTML。DeepSeek 也用了DOM,但更新频率做了节流,只在得分变化时更新。GLM5.3 同样用DOM,但它在通关时用了alert弹窗,而另外两个是在页面上显示文字。
从体验上说,alert会阻塞渲染循环,弹窗关掉之前游戏是卡住的。虽然功能上没问题,但不够优雅。DeepSeek 的节流更新是最合理的做法,避免了每帧操作DOM带来的性能开销。这个细节说明 DeepSeek 在性能意识上略胜一筹。
5. 实操建议:怎么用这些模型做自己的3D小项目
5.1 提示词怎么写才能少踩坑
这次测试让我总结出一个经验:给AI写3D游戏的提示词,一定要把“约束条件”写死。比如“单文件HTML”“CDN引入”“双击可运行”这些,你不写清楚,模型就可能给你一个需要npm install的项目。另外“方向键控制”要明确是“上下左右对应前后左右”,不然模型可能给你映射成WASD。
还有一个技巧:在提示词里主动要求“加注释说明每个函数的作用”。GLM5.3 的注释多可能就是因为它在训练时被强化了这一点,但如果你不要求,另外两个模型可能就不加。注释对于后续修改的价值很大,值得在提示词里占一行。
5.2 拿到代码后的第一轮检查清单
不管哪个模型生成的代码,我建议按这个顺序检查一遍:
- 打开页面看有没有报错(F12控制台)
- 四个方向各走一遍,看边界有没有问题
- 按住一个键然后切窗口再切回来,看按键有没有卡住
- 走到球体旁边看碰撞触发距离是否合理
- 吃完所有球看通关提示是否正常
这五步能覆盖大部分常见问题。我这次遇到的三个bug分别对应第2、3、4步,都是这个清单能抓到的。
5.3 关于 WorkBuddy 这类工具在3D开发中的定位
最近 WorkBuddy 这个词出现频率很高,很多人问它在3D游戏开发里能干什么。我的理解是,WorkBuddy 这类工具的价值在于“工作流编排”——它可以把“生成代码、保存文件、打开浏览器、截图检查”这一串动作串起来。但3D游戏的调试目前还是得靠人眼看、手玩,因为画面渲染的正确性很难用自动化脚本判断。
如果你在用 WorkBuddy 或者类似的助手工具,可以把它用在“批量生成不同参数的版本”上。比如让模型生成5个不同球体数量的版本,然后你手动玩一遍选最好的。这种重复性劳动交给工具,判断和调优留给自己。
5.4 性能优化的几个实用方向
AI生成的3D游戏代码通常不会做性能优化,因为演示场景太简单了。但如果你想把它扩展成更复杂的项目,有几个地方值得注意:
第一,球体数量多了之后,每个球体单独创建Mesh会有性能开销。可以考虑用InstancedMesh来批量渲染。第二,碰撞检测如果是O(n)遍历所有球体,球多了会卡。可以用空间分割或者简单的距离排序来优化。第三,渲染循环里避免每帧创建新对象,比如new THREE.Vector3()这种要提到循环外面复用。
这些优化AI通常不会主动做,因为提示词里没要求。但如果你在提示词里加上“考虑性能,避免每帧创建新对象”,模型是能给出优化版本的。
6. 我个人的一些体会
这次对比做下来,最大的感受是:三个模型在3D游戏这个任务上的差距,没有榜单上看起来那么大。它们都能生成结构完整的代码,都能跑起来,区别主要在于bug的类型和修复成本。Step 5 Preview 最稳,DeepSeek 视觉最好但细节有疏漏,GLM5.3 注释最全但数学错误最隐蔽。
如果你问我日常开发选哪个,我的答案是“看任务”。写业务逻辑代码,DeepSeek 的紧凑风格可能更高效;写需要长期维护的模块,Step 5 Preview 的清晰结构更省心;学习新领域时,GLM5.3 的详细注释有帮助。没有哪个是全能冠军,组合使用才是现实做法。
最后分享一个小技巧:不管用哪个模型生成3D代码,拿到后先别急着改,原样跑一遍,把遇到的问题记下来。然后带着这些问题去问模型“这段代码在XX情况下会出问题,怎么修”,它通常能给出正确的修复方案。这比你自己硬修要快,也能顺便验证模型对自己代码的理解程度。我这次修GLM5.3的角度弧度问题时就是这么干的,它自己给出的修复方案是对的,说明它“知道”正确做法,只是第一次生成时没做对。