最近手里拿到了三款讨论度很高的大模型——Step 5 Preview、DeepSeek V4 Pro、GLM5.3。我这次没有拿它们去写一个静态页面,也没有做常规的代码填空题,而是把同一个3D游戏任务同时丢给了它们:从零生成一个可以直接在浏览器里运行的第三人称3D小游戏。之所以选3D游戏当考题,是因为它最能把模型的代码生成能力逼到墙角。渲染循环、坐标系、相机跟随、碰撞检测、输入事件、资源加载,任何一环出错,浏览器都不给你跑,根本没有糊弄的余地。
这个对比测试适合谁看?首先,正准备用AI辅助做Web3D开发的人,你能看到这些模型在真实项目里的完成度;其次,平时做模型评测的同行,我的测试脚本、提示词模板、评分标准可以直接抄;最后,只是好奇“这些新模型到底谁更能打”的普通读者,我尽量不堆术语,把过程讲清楚。全文都是实测记录,没有参数跑分,只有“能不能跑、跑得顺不顺、手感如何”这些最接地气的结果。
1. 测试背景与评测设计:同一个提示词,同一道考题
1.1 为什么拿3D游戏当考题
写一个静态网页对现在的代码模型来说已经没什么压力了,就好比让实习生整理书架,摆放整齐就算交差。而3D小游戏则完全不是一回事,它要求实习生同时完成搭骨架、布线、装修,还要保证通电之后整个屋子能正常运转。一个最简单的第三人称3D游戏,至少涉及下面几条链路:场景与渲染器的初始化、对象与坐标关系、每帧执行的动画循环、相机跟随视角、键盘事件监听、游戏状态与UI更新。
这里面真正难住模型的地方,不是某个单点功能,而是多系统之间的耦合。举个例子,相机跟随目标物这一件事,就要同时考虑目标物体的世界坐标、相机自身的平滑插值、以及坐标更新时放在渲染循环的哪个位置。顺序错了,画面上物体就会抖动;插值系数给大了,视角就拖泥带水。模型要是没真正理解帧循环和数据流,写出来的代码很容易“看起来全对、跑起来全错”。拿这种任务来测,比单纯问“怎么写碰撞检测”那种八股问答有意义得多。
1.2 统一的提示词与评测标准
这次测试最关键的一条是控制变量。三个模型面对的是同一份提示词,一字不差。我实测过太多次,提示词里稍微换一个词,模型输出风格就会完全跑偏,最后你根本分不清是模型能力差异还是提示词差异。
提示词模板如下:
用Three.js(版本不低于r160)实现一个第三人称3D小游戏:主角是一个立方体,场景中包含若干个静态障碍物和可收集的金币;支持WASD控制移动、空格跳跃;需要有基础的碰撞检测和金币计分UI;整个游戏必须在一个HTML文件中完成,可以直接在浏览器中运行;请输出完整可运行的代码。
评测维度我定成了五个:
- 首轮可用性:生成后不做任何修改,浏览器里能不能直接跑起来;
- 修复效率:在相同的人工辅助下,几轮对话能把游戏调到可玩;
- 代码质量:命名、函数拆分、注释,以及是否把逻辑堆在一个函数里;
- 功能完整度:移动、跳跃、碰撞、拾取、计分这些目标功能完成比例;
- 性能表现:浏览器帧率、是否有明显掉帧。
评测环境就是一台普通开发机,Chrome浏览器,通过本地静态服务器打开HTML文件。不建议用在线代码编辑器做这类测试,因为编辑器自带的三维渲染兼容性和文件服务会把环境影响混进结果里。
1.3 三款模型的使用方式与部署身份
三款模型这次的工作方式不太一样。Step 5 Preview我是通过官方入口对话式调用的,它支持比较长的上下文,适合一次性输出几百行代码这种任务。DeepSeek V4 Pro走的是API,生成速度快,适合快速迭代,但长代码偶尔会截断,需要分段续写。GLM5.3则是在我自己机器上通过vLLM部署后调用的,顺便也试了它的轻量版本glm5.3-flashx,用同样一份提示词看结果差异。
这里必须多说一句GLM5.3的部署。最近问“glm5.3 使用vllm哪个版本的镜像”的人特别多,我自己实测过程中也栽过跟头。vLLM的更新节奏很快,但GLM系列对推理框架的版本要求比较敏感,如果你用的vLLM镜像跟官方适配版本差距过大,启动服务时大概率会遇到算子不支持或者KV Cache初始化失败这类问题。我的建议是:不要无脑追最新版本,去看官方发布说明里明确标注适配GLM5.3的版本号,用那个镜像最稳。对于绝大多数只想做代码生成测试的人来说,干脆走官方云端服务,别折腾本地部署,时间性价比更高。
2. 三款模型的实际表现对比
2.1 Step 5 Preview:首轮完成度最让人意外
Step 5 Preview给我的第一印象是“完整”。它首轮就给出了一个包含场景、控制器、碰撞逻辑、计分系统的完整HTML,打开浏览器直接能跑。按理说这个任务不算简单,我本来做好了第一轮全是废案的准备,结果这个模型直接把骨架搭得很像样。
代码里最突出的一点是模块拆分清楚,没有把所有逻辑塞进一个requestAnimationFrame回调里。它划分了防撞逻辑、金币拾取逻辑、输入处理函数,函数命名也贴切。和另外两个模型相比,它在“工程规范”上的表现明显更接近一个常年写前端的开发者。
当然首轮也不是没有毛病。它的跳跃碰撞判定写得比较理想化,立方体落地时会有一瞬间会穿到地面以下再弹回来,手感偏飘。另外它默认使用了较新的Three.js版本,如果我直接换成低版本CDN资源,会立刻报方法不存在。这说明它对API版本是有依赖的,评估一轮能不能跑通,必须绑定在同一个资源版本下才有意义。
2.2 DeepSeek V4 Pro:生成快,但需要“敲打”
DeepSeek V4 Pro的生成速度是三者中最快的,几乎是“复制提示词、回车、代码马上就出”。首轮代码其实也能跑,但相机跟随效果比较生硬:相机只做了硬坐标同步,没有插值平滑,导致人物一动,视角就像被拽着走,看久了头晕。碰撞检测也做得粗糙,只检测了XZ平面,高度轴没有参与判断,导致立方体可以走到障碍物“头顶”上去。
但它的修复能力非常强。我给了两条增量指令:一是“相机跟随目标时,请使用lerp插值平滑”,二是“碰撞检测需要把物体的高度轴也纳入判断”。它两轮就把问题改到位了,而且没有再引入新的报错。速度与调整容忍度兼得,是这个模型在这次测试里最突出的优势。
需要留意的是长输出截断问题。生成完整代码时,它偶尔会在某个函数中途停下,好像上下文窗口被长代码撑到了极限。遇到这种情况,不要让它重新输出全文,直接让它“从某某函数继续”,保存拼接即可。
2.3 GLM5.3:最愿意反复确认需求的模型
GLM5.3在三个模型里风格很特别:它拿到提示词后没有直接闷头写码,而是先抛了两个问题回来:“视角锁定在主角后方还是自由旋转?碰撞检测是否要考虑地面摩擦?”这种追问在复杂项目里非常加分,因为需求越明确,一次成型的概率越高。但在单轮生成测试里,追问会拖慢节奏,如果你追求一次出结果,要在提示词里提前把它可能问的问题都主动写清楚。
它生成的结果在细节上做得最丰富:不仅完成了基础功能,还给UI加了分数动画,金币拾取时会有缩放消失效果,场景里额外放了几棵低多边形树木。但从“单HTML文件可直接运行”这个约束来看,它反而做得最吃力。它试图生成木材纹理贴图并以内嵌base64方式塞进代码,结果文件体积暴涨,加载反而变慢,部分纹理还因为跨域策略无法显示。在追求极简落地的场景里,这属于好心办坏事。
我本地部署的GLM5.3非轻量版本,响应速度明显比官方API慢一些,但代码生成任务本身不需要高并发,多等几秒影响不大。如果想在低资源机器上跑同样的任务,glm5.3-flashx是更务实的选择,它牺牲了一点推理深度,换来了更低的显存占用和更快的首字延迟。
2.4 对比汇总表
| 评测项 | Step 5 Preview | DeepSeek V4 Pro | GLM5.3 |
|---|---|---|---|
| 首轮可用性 | 高,直接可玩 | 中,能跑但体验一般 | 中,功能完整但有资源加载隐患 |
| 修复到可玩所需轮次 | 3轮 | 2轮 | 4轮 |
| 功能完整度 | 移动、跳跃、碰撞、计分齐全 | 齐全,碰撞需修正 | 齐全,额外加了动画与树木 |
| 代码组织 | 清晰,模块化 | 尚可,部分函数偏长 | 较清晰,但资源内嵌冗余 |
| 性能表现 | 稳定60帧 | 稳定60帧 | 纹理加载后偶发掉帧 |
| 综合体验 | 最适合直接落地 | 最适合快速迭代调试 | 细节最丰富但需要“做减法” |
需要说明的是,表里的轮次是在我作为人工调试者的辅助下完成的,并不是模型全自动修复。真实的开发场景里,也没有哪个模型能完全脱离人来跑完一个3D项目。
3. 核心环节拆解:AI生成3D代码的关键点
3.1 渲染循环与相机跟随:模型是否理解帧循环
评测过程中我最看重的一点,是模型生成的代码里渲染循环是否规范。很多刚接触Three.js的人会直接把整个游戏逻辑写在全局作用域,然后一股脑丢进requestAnimationFrame里,第一轮能跑,第二轮就乱套。优秀的三维游戏代码,一定会有清晰的主循环分层。
这次三家模型都正确使用了clock.getDelta()来做每帧时间差计算,而不是直接累加一个固定步长。这一点让我比较意外,说明训练数据里规范代码的比例确实提升了。以其中一个模型给出的循环为例:
const clock = new THREE.Clock(); function animate() { requestAnimationFrame(animate); const delta = clock.getDelta(); player.update(delta); camera.position.lerp(cameraTarget.position, 0.08); camera.lookAt(player.position); renderer.render(scene, camera); } animate();这段代码的优点是结构干净,插值系数0.08带来的跟随手感比较适中,不会过于僵直,也不会因为延迟太高让视角甩到奇怪的位置。缺点是lerp方法要求cameraTarget.position每帧都被更新,如果玩家的移动逻辑没有同步修改这个向量,相机就会“追着一个静止点跑”。三个模型在这一点上的表现差距,直接决定了视角跟随时是否会出现漂移。
对于想要自己上手改代码的读者,注意一点:插值系数不要直接用固定数值当速度,更优雅的做法是乘以delta,让插值速率与帧率解耦。模型第一次生成往往不会考虑这么细,需要人提出“请把插值系数与delta相乘”这类改进。
3.2 碰撞检测:从“能用”到“手感好”
碰撞检测是这次测试里暴露问题最多的环节。三种模型首轮给出的碰撞方案出奇一致:都选择用AABB包围盒做粗略相交判断,而不是引入物理引擎。这个选型对单HTML文件来说是明智的,物理引擎会加几百KB体积,性能也会受到影响,对这样一个超轻量小游戏并不划算。
但实现细节差距就出来了。有模型写的碰撞检测是这么处理的:检测到碰撞后直接把速度向量清零,然后让角色停留在原地。听起来没问题,实际跑起来会感觉角色像撞在一堵隐形的墙上,稍微斜着走就会被“卡死”,因为垂直于碰撞面的速度分量被清零的同时,平行方向的滑动也没了。
更好的做法是保留切向速度,只把法线方向的速度分量置零。我在修DeepSeek V4 Pro版本时,给它贴了一句指令:“碰撞后希望角色能沿障碍物边缘滑动,而不是完全停下,请修改速度处理逻辑。”它很快就把速度向量做了投影分解。这种修复方式比重新推翻整个碰撞逻辑省事得多。
跳跃碰撞则是另一个重灾区。所有模型首轮都会把“落地判定”做得特别简单:当Y坐标小于等于地面高度,就认为已经落地。这会导致高帧率下角色看起来悬浮、低帧率下角色直接穿模。正确做法是记录上一帧的位置,检测到“上一帧在地面以上、这一帧穿到了地面以下”时才触发落地响应。我们人工加了这条约束后,三个模型都能正确修改,但这个过程恰好说明了为什么3D游戏测试比普通网页测试更能考验模型的推理能力。
3.3 单HTML文件的资源管理:模型常在这里翻车
单HTML约束本身是一种压力测试。Three.js的完整核心库接近600KB,通过压缩CDN引入之后虽然还好,但如果再叠加纹理贴图、声音文件、模型文件,单纯塞进HTML里很容易失控。GLM5.3这次生成的树木使用了内嵌base64纹理,直接把HTML文件撑到了接近8MB,浏览器启动加载时要卡好几秒。首帧渲染的体验非常糟糕。
正确的处理思路是分三类:库文件用CDN的importmap方式声明;纹理与模型文件放相对路径的本地目录;游戏代码作为内联脚本放在同一HTML里。这样既严格满足了“单HTML”的展示要求,又不让文件体积失控。如果你想让AI帮你生成这类项目,最好在提示词里明确写一句“纹理不允许内嵌base64,使用外链相对路径”,能避开一大部分资源加载问题。
4. 实操复盘:我是怎么把三个版本调到可玩的
4.1 完整调通流程:以Step 5 Preview为例
为了让流程可复现,我以Step 5 Preview为例记录一次完整的调通过程,从零到可玩一共花了不到二十分钟。
第一步,本机创建项目目录,新建index.html,并把Three.js通过importmap引入。这里要特别注意,不要直接把某个CDN地址复制进去就不管了,因为模型生成的代码往往是基于特定版本API的,版本不一致会导致“方法不存在”之类的低水平报错。我固定用的是0.160.0版本,所有会话都把版本号写死在提示词里。
第二步,让模型生成主游戏脚本,并明确要求它写在一个