先说明一句:这个周末我哪儿都没去,就坐在电脑前干了一件事——把同一个3D游戏需求分别喂给Step 5 Preview、DeepSeek V4 Pro、GLM5.3,让三个模型在完全相同的条件下各自写一遍,然后我逐个把代码跑起来、修错、玩通关。最近这些AI模型铺天盖地都在宣传"写代码能力代际提升",但宣传归宣传,真正让它写一个包含交互、碰撞、计分、计时、3D场景渲染的完整小游戏,很多问题才会暴露出来。这篇文章就记录这次实测的完整过程,包含三份实现方案的对比、我踩到的坑、以及怎么用提示词把这类3D游戏需求准确传递给AI模型。想用AI做网页3D游戏、或者在做AI辅助开发选型的朋友,这篇应该能帮你少走不少弯路。
1. 为什么选择3D游戏作为评测场景
1.1 3D游戏比CRUD应用更能暴露AI短板
现在大多数AI写代码的评测还停留在"生成一个待办事项列表"或者"写个登录接口"这种层级。这类任务说实话已经不能拉开模型之间的差距了,连小参数模型都能背下来。但3D网页游戏完全是另一回事:
它需要同时处理Three.js版本兼容性、三维坐标空间、光照与阴影参数、相机控制、射线碰撞检测、动画循环、状态管理、UI交互。任何一个环节出了偏差,页面要么黑屏,要么报错,要么角色直接穿模到地底下。这种"多系统协同"的场景,最能看出模型到底是背了文档,还是真正理解了3D编程的底层逻辑。
再加上Three.js本身的API一直在变,旧的Geometry类被移除、THREE.Face3消失、outputEncoding被弃用。如果模型训练数据里混入了过时的代码片段,生成出来的东西大概率跑不起来。这正好能过滤掉那些"看起来不错但全是过期API"的AI生成结果。
1.2 测试需求设计:一个"小球收集金币"的Three.js单页游戏
为了公平,我给三个模型发的需求完全一致,一个字都不改。游戏需求是这样的:
- 使用Three.js(明确要求最新的ES模块版本)开发一个第三人称3D小游戏
- 玩家通过键盘WASD或方向键控制一个球体角色在场景中移动
- 场景为露天平台,有地面边界,边界处有半透明墙体阻止角色走出
- 场景中随机分布10个旋转的立方体金币,角色触碰到金币后金币消失、得分增加
- 场景中有若干静态障碍物圆柱体,角色碰撞到障碍物后不能穿过
- 画面顶部显示实时得分和60秒倒计时
- 时间结束后弹出结算界面,显示最终得分和"重新开始"按钮
- 所有代码必须在一个HTML文件中完成,不需要后端,双击即可运行
测试环境统一为:Chrome浏览器、本地静态服务器启动、Three.js通过CDN加载r160版本。我人工记录每个模型的首次可运行率、需要人工修复的错误数、以及达到"可玩状态"的耗时。
这里有个细节要说明:我没有让模型"自由发挥"而是刻意给了精确的交互规则,因为游戏开发最耗时间的往往不是写代码,而是需求理解。给模型一个模糊的"做一个3D游戏",它给的方案通常也是模糊的。当需求足够具体,才能真正比出模型的代码执行力差距。
2. 评测维度与"我的人工修正"标准
2.1 评分维度设计
三个模型各自生成的HTML文件,我都会按以下五个维度打分,每个维度20分,总分100分:
| 维度 | 考察重点 |
|---|---|
| 代码可运行性 | 首次在浏览器中打开是否直接报错,能否通过简单修复跑起来 |
| 功能完整度 | 需求中列出的10个功能点是否全部实现,有没有遗漏 |
| Three.js API正确性 | 是否使用当前版本API,是否存在废弃类的调用 |
| 可维护性 | 代码结构是否清晰,变量命名是否合理,是否方便二次修改 |
| 性能与体验 | 帧率是否稳定,相机视角是否舒适,操作手感是否顺畅 |
2.2 人工修正的边界控制
评测过程中,我允许自己对三个模型的代码进行修正,但每次修正都严格记录。所谓"修正",只限于修复崩溃、消除报错、补全因模型输出截断导致的不完整代码。如果某个功能的结构性设计和需求描述不一致,我选择保留它然后计入功能完整度的扣分,而不是替模型重写功能。这样能最大限度还原真实用户的使用体验——你让它写游戏,你不会想帮它重新设计游戏逻辑,你只希望它跑起来。
另外,我还特别关注了一个隐藏指标:模型对自己代码的解释能力。在每轮测试结束后,我会追问模型的实现思路、问它"为什么这里用Raycaster而不是直接判断坐标距离",看它能否给出符合3D开发常识的回答。这个指标虽然不直接反映在打分表里,但对真实开发场景非常重要。
3. Step 5 Preview 实测:第一版就能跑,代价是"代码聊天味"略重
3.1 首次生成结果与运行情况
Step 5 Preview给我的第一印象是:生成速度非常快,几乎是我把需求粘贴进去不到30秒,整份HTML代码就出来了,而且逻辑结构看起来很完整——场景初始化、相机、光照、角色、障碍物、金币、UI全都有。我没有犹豫,直接保存文件、启动本地服务器、打开浏览器。
页面出来了,球体角色好好地站在平台上,光照正常,金币在旋转,倒计时在走。说实话那一刻我有点意外,因为很多模型第一次生成3D项目时连renderer.render都不调用,能直接看到画面的确实不多。
但很快问题就暴露了。我按下W键,球体确实往前滚动了,但相机完全没有跟随。就和球在前方跑,镜头还停留在原点一样。我翻了代码才发现,它的相机跟随逻辑是在animate循环里调用了一个updateCamera函数,但函数内部只设置了一次camera.position,没有在每一帧里用球体的世界坐标去更新。等于这个函数只在初始化时生效了一次。
再往下测,碰撞检测也有问题。与金币的碰撞它用的是每帧遍历所有金币,判断中心距离是否小于一定值,这个思路没问题。问题出在与障碍物的碰撞上:它只检测了球体中心与圆柱体中心的平面距离,没考虑圆柱体的半径。结果就是球明显已经和障碍物重叠了,但系统判定还没撞上。
3.2 修复最多的点:相机跟随与物理手感
我在对话里直接把问题反馈给它:"相机应该每帧跟随球体,且需要把球体的移动方向偏量纳入相机目标位置计算",它很快给出了修正方案。第二次给出来的代码里,相机跟随逻辑改成了在animate循环中重新计算camera.position.x和camera.position.z,再通过camera.lookAt(ball.position)锁定视线方向。
障碍物碰撞的修复也简单但有效——它在判断距离时加入了圆柱体半径,把碰撞条件从distance < ballRadius改成了distance < ballRadius + cylinderRadius。修完之后手感明显正常了,不会再出现"看着撞上了其实没判定"的怪象。
3.3 代码风格观察:注释多到影响阅读
整个过程中,Step 5 Preview最让我不舒服的一点是代码里的注释密度。它几乎给每一行都写了中文注释,包括const scene = new THREE.Scene(); // 创建场景这种完全可以从代码本身理解的内容。注释本身无害,但当代码量膨胀到400行以上时,满屏注释反而干扰阅读,尤其是你希望快速定位某段逻辑的时候。
我个人的习惯是"注释解释为什么,而不是解释是什么"。Step 5 Preview生成的代码,一大半注释都在翻译代码本身,这在教学场景里可能是优点,但在工程场景里绝对是减分项。所以我在可维护性维度上给了它偏低的分数。
4. DeepSeek V4 Pro 实测:工程化意识最强,但慢热
4.1 代码结构和模块划分最像老手
如果说Step 5 Preview像一个热心的教学型助手,那DeepSeek V4 Pro生成的第一版代码就像一个在正经团队里干过几年的前端工程师写的。它没有把所有逻辑塞进一个init函数里,而是天然分出了几个职责清晰的区块:createScene负责场景和灯光,createPlayer负责角色,createEnvironment负责地面与障碍,createCoins负责金币阵列,gameLoop负责动画和碰撞。
这种划分的好处是,当我需要单独调整金币的旋转速度时,完全不需要去找全局逻辑,直接在createCoins函数里改即可。这对真实项目维护的意义非常大。而且它的变量命名明显更讲究,比如moveDirection、collisionRadius、elapsedTime,读代码的人可以毫不费力地理解每个变量在干什么。
DeepSeek V4 Pro在第一次生成时还做了一个让我眼前一亮的决定:它主动用了THREE.CapsuleGeometry来做成障碍物之间的连接柱,而不是像多数模型那样只用竖起来的圆柱体。虽然从需求角度来说,加连接柱属于超纲发挥,但视觉效果确实比单纯立几根柱子丰富不少。
4.2 首次运行的翻车点与修正
不过DeepSeek V4 Pro也有翻车的时候。我第一次打开它生成的页面,画面渲染出来了,球也能控制,但页面左上角的得分计数一直卡在0,无论我控制球体撞了多少金币,分数就是不动。
排查之后发现原因在事件监听上。它的金币碰撞处理逻辑本身没问题,但金币被收集后只是设置了coin.visible = false,同时从数组里过滤掉。坏就坏在它用的是coins = coins.filter(...)而不是coins.splice(...),而内部的碰撞检测循环每一帧创建的是新数组副本,导致后续帧里的coins数组引用和渲染循环里的引用不一致。这种情况在静态代码审查里很难看出来,必须真正运行一遍并观察行为才能发现。
另一个小问题是场景亮度偏低。它把AmbientLight的强度设成了0.3,因为没有添加HemisphereLight,导致整个场景灰扑扑的,金币的金色质感完全体现不出来。我把环境光强度调到0.8后,画面观感立刻提升一个档次。
4.3 对复杂需求的拆解能力
DeepSeek V4 Pro还有一个很突出的特点:当我追问它"你实现这些功能时是怎么安排优先级的",它能非常清晰地罗列出思考顺序——先搭渲染基本盘,再处理物理碰撞,然后才是UI和计分,最后做性能优化。这其实就是资深开发者常说的"先跑通主链路,再补细节"。
这一点在三个模型里只有DeepSeek V4 Pro做到了。Step 5 Preview是"一股脑全铺开",GLM5.3是"先设计状态再填充细节",只有DeepSeek V4 Pro的策略是真正贴合实际开发验证节奏的。
5. GLM5.3 实测:需求理解最深,但也踩了兼容性老坑
5.1 交互体验:对话里最有"产品思维"
GLM5.3这次的表现可以从几个不同侧面来看。先说最直观的感受:它在接收需求后没有立刻甩代码,而是先问了我三个问题。第一,"是否需要考虑移动端触屏操作兼容";第二,"球体碰到边界墙体时希望是硬阻挡还是滑行阻挡";第三,"60秒倒计时结束后是否要同时记录历史最高分并保存在本地"。
这种主动澄清需求的行为在真实开发场景里极其珍贵。大多数情况下,用户也不知道自己到底要什么,如果模型一上来就写几百行代码,最后往往要返工。GLM5.3这种"先花30秒把需求边界修复清楚"的做法,像极了一个靠谱的产品经理在开发前做的需求评审。
我其中两个问题的回答都是"不需要",第三个问题我让它做进结算界面。于是它后面生成的版本里,就真的在结算弹窗上加了localStorage记录历史最高分的功能,而且处理得干净利落。
5.2 踩坑:旧版API与新版Three.js冲突
但GLM5.3也踩了一个让我没想到的坑。我用的是Three.js r160版本,而它第一次生成的代码里大量使用了THREE.Geometry和THREE.Face3。这两个类在r125之后就已经被彻底移除了,现在调用会直接抛出THREE.Geometry is not a constructor的错误。
这说明GLM5.3的训练数据里混入过大量上古时代的Three.js教程。更麻烦的是,它不只是在一个地方用了旧API,FlatShading、LambertMaterial也混着用,像是把几年前的代码风格和当下的代码风格缝在了一起。
修复本身花了我大概二十分钟。BufferGeometry替代Geometry不是简单的替换类名,还要把原来的faces数组改写成position数组和index数组的组合。我直接选择在对话里告诉它"请用BufferGeometry重写所有几何体生成代码",它立刻给出了新版写法。这个过程中的经验是:让AI修自己的代码,最好的方式不是手动帮它改,而是精准指出API层面的根本问题,让它自己重构。
5.3 计时器和结算界面的完成度
单论功能完整度,GLM5.3这版是所有模型里最让我满意的。它的倒计时实现采用Date.now()差值计算,而不是简单累加deltaTime,这样即使在游戏过程中切换标签页导致浏览器节流计时器,回来之后倒计时依然准确。它的结算界面也带了完整的UI状态机:暂停时显示提示层、倒计时归零后能正确中止所有动画循环、重新开始按钮会重置所有得分和金币状态。
这种细节熟练度是三个模型里最出挑的。DeepSeek V4 Pro和Step 5 Preview的重新开始功能都是简单刷新页面,只有GLM5.3是真正在代码层面复原了所有游戏状态。
6. 横向对比:同一需求下三个模型的真实战绩
6.1 各维度打分表
综合三轮测试结果,我给出的评分如下表:
| 维度 | Step 5 Preview | DeepSeek V4 Pro | GLM5.3 |
|---|---|---|---|
| 代码可运行性 | 18(首版可跑,修1处相机问题) | 17(首版可跑,修事件监听BUG) | 13(首版无法运行,需重写几何代码) |
| 功能完整度 | 16(障碍物碰撞判定不准确) | 18(全部实现,额外加了场景装饰) | 19(全部实现,含历史最高分) |
| Three.js API正确性 | 15(个别过时写法但无致命错误) | 17(整体标准,部分属性未更新) | 10(大量旧API混用) |
| 可维护性 | 12(结构性弱,注释过于冗余) | 19(模块划分清晰,变量命名优秀) | 16(结构不错但命名偏随意) |
| 性能与体验 | 15(手感一般,相机略死板) | 17(运行流畅,操作反馈完整) | 18(辅助交互完整,体验细节舒适) |
| 总分 | 76 | 88 | 76 |
三个模型的总分相差不大,但失分逻辑完全不同。Step 5 Preview输在代码结构和注释习惯,GLM5.3输在知识更新滞后导致的API误用,DeepSeek V4 Pro则是综合表现最接近"合格开发者"水平的那一个。
6.2 代码量、修复次数与耗时对比
在代码规模和修复成本的统计数据上,差异也很明显:
| 指标 | Step 5 Preview | DeepSeek V4 Pro | GLM5.3 |
|---|---|---|---|
| 生成代码行数 | 487行 | 523行 | 461行 |
| 首次运行需修复错误数 | 2处 | 2处 | 6处 |
| 达到可玩状态耗时 | 12分钟 | 9分钟 | 28分钟 |
| 达到可玩状态后的bug存量 | 1个(穿模手感略差) | 0个 | 0个 |
GLM5.3的28分钟耗时完全是被旧API拖累的。如果把Geometry重写BufferGeometry的时间排除,它代码本身的逻辑错误几乎可以忽略。这提醒了我一个现实问题:模型参数再强,如果训练数据里的框架版本过于陈旧,它给出来的"正确答案"在当下环境中就是跑不起来的。
6.3 三个模型的性格画像
跑完三轮,我对这三个模型建立了非常明确的使用画像:
DeepSeek V4 Pro最像一位"经验丰富但话少的架构师"——它不会主动问你需求边界,但给你交付的代码大概率可以直接进代码仓库;Step 5 Preview更像"热情的新人导师"——它愿意把每个细节掰开揉碎讲给你听,但真正接手项目时你会嫌它烦;GLM5.3最有"产品心"——它关心的是你最终拿到的东西好不好用,但是对脚下地基的版本变迁不够敏感。
7. 三款模型在3D游戏开发中的通用避坑经验
7.1 提示词里必须写清楚的5件事
通过三轮实测,我总结出让AI模型稳定产出可运行3D游戏的提示词要素。如果你只是给个"做一个3D游戏"的粗需求,任何一个模型都会产出"引发无限返工"的半成品。但如果你在提示词里写清楚下面五条,基本上每个模型的首版完成度都能上一个台阶:
- 指定Three.js版本号并告诉它"只允许使用该版本API",例如
"请使用Three.js r160的官方文档API编写",直接切断旧知识的输入通道。 - 明确"必须在一个HTML文件内完成,禁止拆分JS文件",逼它集中精力组织单一文件的结构逻辑。
- 写清游戏的核心状态机:运行中、暂停、结束、重新开始,并要求它对每个状态做出具体的UI反馈。
- 明确碰撞检测的判定方式:是用距离阈值还是用射线,以及障碍物半径、角色半径分别由哪些变量承载。
- 要求"先列出TODO清单再编写代码",这一步能逼着模型在写代码前快速做一次需求拆解,避免想到哪写到哪。
7.2 AI生成3D代码最常见的三类错误
实测过程中,三种模型都出现过下面这些同类问题,在这里一并指出:
第一类是光照参数极端化。很多模型理解不了现实光照单位,喜欢把环境光设为0.1、点光源设为2.5,导致场景要么暗得看不见,要么亮得刺眼。标准做法是:AmbientLight强度0.4到0.6,DirectionalLight强度0.8到1.2,必要时补一个HemisphereLight来模拟环境漫反射。
第二类是动画循环注册重复。有的模型会在init里调用一次requestAnimationFrame,又在animate函数里再次调用,结果渲染循环执行了两遍,帧率直接减半但肉眼不易察觉。这次实测里DeepSeek V4 Pro和GLM5.3都出现过,跑起来之后能明显感觉到角色移动"发飘"。
第三类是相机跟随的"死区"问题。多数模型实现相机跟随就是简单的camera.position = ball.position + offset,但角色快速转向时,镜头会被拉扯得很生硬。一个更平滑的方案是让相机目标位置做插值移动:cameraTarget.lerp(ball.position, 0.1),镜头就有了阻尼感,动态视觉舒适度高很多。
7.3 即使AI写代码,也要建立自己的验证清单
最后的体会可能有点反直觉:三个模型中得分最高的DeepSeek V4 Pro,它的代码质量确实最高,但这并不代表它省掉了人工审查的必要性。在第二轮测试里,那个硬币收集计分始终为0的BUG,如果不花两分钟实际操作一遍,光靠读代码很难定位到filter()的数组引用问题上。
所以我现在用AI写3D游戏,都会建立一份非常机械的验证清单:第一步确认渲染循环只注册一次;第二步确认所有几何体使用BufferGeometry;第三步手动操控角色碰撞每一个障碍物和金币;第四步测试倒计时结束后的状态转换;第五步刷新页面确认重开功能。这套清单在人工写代码时也是隐形的,但AI生成代码后,隐形的东西会变成显性的坑,必须靠清单来兜底。
下次如果你也打算用AI从头做一个网页3D游戏,我的建议是别急着挑哪个模型最强——先把需求文档写到"AI不需要追问就能动手"的程度,再让两到三个模型各写一版,互相参考着拼一个最终版。实测下来,DeepSeek V4 Pro提供的骨架最稳,GLM5.3在交互细节上思考得最深,Step 5 Preview则能在你完全懵的时候把你教会。三个模型各有各的救场方式,但最终扮演"主程"把一切揉在一起的,还是你自己。