昨天凌晨把 Step 5 Preview 的接口申请下来时我顺手做了个决定不让它单测直接扔进一个三人小组——DeepSeek V4 Pro、GLM5.3 和 Step 5 Preview用同一个 3D 游戏任务同台竞技。这个任务不复杂做一个能在浏览器里直接跑的 3D 滚球小游戏不限定引擎、不限定代码结构、不给参考实现只要求最后打开网页就能玩画面别太丑手感别太拉垮。选 3D 游戏当试金石是因为它对模型的要求很立体长上下文理解、空间几何计算、物理碰撞、相机控制、UI 布局甚至代码审美全都会被摊开来看。单测“写个排序函数”根本看不出模型之间的区别只有这种综合性任务才能暴露真实水平。这篇文章就是完整实测记录。我会把三个模型的提示词、生成代码、Bug 修复过程、部署细节以及我实际踩过的坑全部写出来。如果你是做 AI 编程工具选型、本地模型部署或者单纯想看看当前这些大模型写 3D 代码到底什么水平这篇文章应该能帮你省掉不少试错时间。1. 为什么 3D 游戏是最合适的“同题作文”1.1 一道题同时考验长上下文、数学和代码组织能力很多人测模型还停留在“帮我写个贪吃蛇”这种级别说实话已经测不出差距了。贪吃蛇本质上是一个二维数组的遍历问题代码量小、状态简单哪怕一个能力很平庸的模型也能通过背诵相似代码混过去。3D 游戏完全是另一个量级。首先它需要模型真正理解三维坐标系。Three.js 里物体的 position、相机的 lookAt、光照的方向这些都不是能从常见代码片段里简单拼接出来的。稍不注意就会出现“物体在画面里消失了”“相机倒着看场景”“小球穿墙而过”这类问题。其次3D 游戏天然涉及物理引擎或手动碰撞检测。而碰撞检测的高低位判断、跳跃重力加速度、边界约束这些如果模型没有足够的空间想象能力很容易写出“小球明明碰到障碍物了却直接从中间穿过去”的逻辑。更关键的是代码组织能力。一个 3D 小游戏至少包含场景初始化、循环渲染、输入监听、碰撞处理、UI 状态几个模块。模型需要在一个上下文里同时记住这些模块的职责保证相互之间不冲突。这对长上下文窗口的“有效注意力”是很大的考验。我实测中见过不少模型前面写得很正常写到 200 行之后开始遗忘最初的变量名甚至重复创建同一个 renderer。3D 游戏任务正好能把这种“上下文失忆症”逼出来。1.2 固定测试环境的三个关键约定虽然我想看“自由发挥”但完全自由会导致结果不可比。所以我在测试前做了三个约定尽量把变量控制在模型本身。第一个约定统一使用 Three.js 作为渲染层。原因很简单它是最主流的 WebGL 封装库所有模型都见过大量相关训练数据不会出现“某个模型没见过某小众引擎”的意外劣势。第二个约定不限制代码文件数量和组织方式。允许模型只生成一个 HTML 文件也允许它生成模块化结构我全部照单全收。第三个约定不提供任何示例代码只给需求描述。这样每个模型对需求的理解方式才会完整体现出来。评分维度我也提前定好了首次可运行率生成代码直接打开能不能跑、核心玩法完整性能不能滚球、能不能跳跃、能不能达成终点、物理手感碰撞是否准确、是否穿模、Bug 难度运行时报错数量与严重程度、代码可读性和可维护性。每个维度权重不同玩法完整性占最大头因为游戏首先得“能玩”。2. 同一道题三种完全不同的解题思路2.1 Step 5 Preview一上来就走“正规军”路线Step 5 Preview 给我的第一印象是它不像在“回答问题”更像在“做项目”。收到需求后它没有立刻甩出一大坨代码而是先列出了项目结构建议包括入口文件、场景管理模块、碰撞检测模块、UI 模块还说了一句“建议把物理参数抽成常量方便后边调手感”。这个细节很加分。因为 3D 游戏开发里最让人头疼的不是“写不出来”而是“写出来之后没法调”。如果模型把所有数字都写死在函数里用户想调一下跳跃高度得在一千行代码里搜 0.5 这个数字。Step 5 Preview 主动把重力加速度、跳跃力度、移动速度这些参数集中成配置项属于是懂游戏开发的人才会做的事。生成代码的运行效果也不错。首版就实现了滚球移动、跳跃、障碍碰撞检测、终点判定、计时 UI浏览器控制台没有红色报错。第一次打开就能玩这个“首次可运行率”在当前模型里已经算优秀水平。后面我会详细拆它的实现。2.2 DeepSeek V4 Pro代码量大但物理参数“凭感觉写”DeepSeek V4 Pro 的风格完全不同。它给我的第一版程序非常慷慨洋洋洒洒写了将近 900 行代码把所有内容全部塞进一个 HTML 文件。功能齐全甚至额外加了小地图和粒子特效。这一点值得肯定它的“产品意识”很强知道什么功能能提升 demo 的完整度。但它的问题也很明显物理参数几乎全靠拍脑袋。比如跳跃速度设置了 8.5重力加速度设置了 9.8看起来像是地球重力但实际配合跳跃高度和帧率以后小球跳起来像火箭升空滞空时间长得离谱。这个就是“单看参数合理组合起来不合理”的典型毛病。模型如果不理解“帧率、位移、速度”三者之间的实际换算关系很容易写出一堆单独看没错、合起来手感奇怪的值。修复 Bug 时也暴露了它的一些问题。多轮对话修改中它修好一个穿模问题后往往会把之前正确的碰撞回调条件改坏。这个后面专门说。2.3 GLM5.3脑洞最大代码风格最“野”GLM5.3 给我的感觉是“美术生转行写代码”有想象力但不太守规矩。它没有用 Three.js 标准做法而是想用 BufferGeometry 手动构建一个低多边形场景甚至自己写了简单的光照公式。这个方案理论上可行但工作量比 Three.js 自带 MeshStandardMaterial 大很多而且很容易出问题。它的代码命名风格也很随性。变量名从 ball1、box2 到 tmp、temp、test 全都有函数之间边界模糊大量逻辑堆在一个 update 函数里。这导致它的代码第一次运行也成功了但想改点东西非常痛苦。你需要很仔细地读代码才能搞明白某个变量到底在哪里被修改过。不过 GLM5.3 有一个优点是另外两个模型比不了的它在“游戏创意”上更强。比如它主动做了一个“场景随通关进度渐变”的小效果虽然实现简单但展示出了理解游戏体验的潜力。我后来在测试 glm5.3 flashx 时也验证了这一点闪速版代码生成速度快很多但创意输出会更“飘”需要更强的提示词约束才拉得回来。3. 实测实录同一个“滚球闯关”三种落地方案3.1 我给出的统一任务需求为了让三个模型拿到的是同一个需求我写了一份提示词内容如下请用 Three.js 开发一个 3D 滚球闯关小游戏。玩家使用键盘 WASD 或方向键控制一个小球在平台上滚动目标是到达终点区域。过程中有若干静态障碍物和移动障碍物小球碰到障碍物后不立即死亡而是会被弹开并扣除一些时间。小球掉出平台则游戏失败。需要包含跳跃功能、碰撞检测、终点判定、计时 UI、重新开始按钮。代码需在单个 HTML 文件中可直接运行使用 CDN 引入 Three.js。请确保首次运行无报错并给出关键参数配置说明。注意我特别强调了两点碰到障碍物“不立即死亡而是弹开并扣时间”以及“首次运行无报错”。前者是为了考验模型对自定义游戏规则的理解后者是为了逼它自己检查语法和资源加载。很多模型写代码时为了“好看”会加一堆没用但容易出错的装饰这个约束能有效过滤掉那种行为。3.2 Step 5 Preview 的实现结果拆解Step 5 Preview 生成的 HTML 文件约 320 行结构非常清晰HTML 里只放了一个 canvas 和一个遮罩层所有逻辑都在script标签中。它用了一个比较小的细节游戏状态用常量定义分别是 READY、PLAYING、WIN、FAILED。后续的 UI 切换全部基于状态判断而不是直接散落地操作 DOM。这个设计让“重新开始”按钮的实现变得很简单只要重置状态再调用一个 reset 函数就行不需要手动清理一堆全局变量。它的小球控制逻辑如下const speed 8.5; const jumpForce 7.2; const gravity 22; const friction 0.985; function updatePlayer(delta) { const acc new THREE.Vector3(); if (keys.w) acc.z - 1; if (keys.s) acc.z 1; if (keys.a) acc.x - 1; if (keys.d) acc.x 1; if (acc.length() 0) { acc.normalize().multiplyScalar(speed * delta); ball.velocity.add(acc); } ball.velocity.multiplyScalar(friction); ball.velocity.y - gravity * delta; ball.position.addScaledVector(ball.velocity, delta); }这里最值得说的是friction的用法。很多模型会写一个复杂的阻尼公式但 Step 5 Preview 选择用multiplyScalar(0.985)做帧间速度衰减。这个方案虽然不物理但在游戏手感上非常有效小球停下来很快不会像溜冰一样滑个没完。它把 jumpForce 和 gravity 的比例也设置得比较合理跳跃后最高点大约在 1.2 米左右配合平台高度刚好能让玩家跳过障碍物又不会飞得太高导致视角跟不上。相机跟随也做了平滑用 Lerp 插值让相机跟在小球后面而不是硬切坐标。这个细节让整个 demo 的观感立刻上升了一个档次。首测运行的时候我第一反应是“这不像 AI 写的”因为动态平滑感做得太自然了。3.3 DeepSeek V4 Pro 的实现结果拆解DeepSeek V4 Pro 的代码量明显更大功能也更花哨。它额外加了地面网格、环境光加方向的组合光照、粒子脚印效果甚至还加了一个小地图。首次打开画面很漂亮信息密度很高。但核心玩法的操作手感需要人工调参数才能达到可玩状态。它的小球控制逻辑用了“加速度 阻尼”的模型方向处理上没有什么问题问题出在跳跃参数上。它写的跳跃速度是 10.2重力是 9.8人眼看起来似乎“符合物理直觉”实际代入 Three.js 的帧循环后小球跳起 3 秒都不落地整个游戏变成“飞行模拟器”。我把这个 Bug 反馈给模型它的第一次修复只是把 gravity 从 9.8 改成 18但跳跃速度没变依旧偏高。直到我明确说“跳跃最高点不应该超过 0.6 米”它才把跳跃速度降下来。这说明 DeepSeek V4 Pro 对“物理公式”的理解没问题但对“游戏手感参数”缺乏体感判断。它知道重力公式是什么但不知道一个 3D 小游戏里参数应该是多少。这类模型的代码更像“完成作业”而不是“做出一款能玩的游戏”。碰撞检测方面它用了基于 AABB 的碰撞盒。问题在于它把所有障碍物都加了碰撞盒但没给平台边缘加边界检测导致玩家可以从小球直接从侧面掉出平台——这在游戏设计里是不允许的因为你不希望玩家“偶然绕过去”而不是“靠操作过关”。这算是游戏逻辑设计的疏漏。3.4 GLM5.3 的实现结果拆解GLM5.3 的代码是最让人意外的。它没有按套路引入 Three.js 的标准几何体而是直接用 BufferGeometry 构建了一个 30 面体的低多边形小球还自写了顶点法线最后效果是“闪亮小钻石”风格。虽然代码很野但呈现出来的视觉效果确实有辨识度。它的问题主要在代码组织上。大量逻辑堆在主循环里update 函数接近 150 行混杂了输入检测、碰撞检测、UI 更新、场景变色切换。这就导致它第一次跑通以后我想调整跳跃力度却发现 jumpForce 这个变量在三个不同位置被赋值了根本不知道哪一份生效。碰撞检测用的是“距离判断法”检测小球与障碍物中心点的距离是否小于两者半径之和。这个方法对球体障碍很准但遇到长方体障碍物就有问题——它会在长方体对角线方向产生“额外碰撞”小球明明离角落还有一段距离却被判定撞上了。我让 GLM5.3 修复这个问题它的方案是“把障碍物全部换成正球形”虽然有效但本质上是绕开了问题而不是解决问题。不过它的移动障碍物设计很有想法一个来回巡逻的滑块速度随游戏时间加快。这个设计增加了可玩性其他两个模型都没有主动加这个机制。这说明 GLM5.3 在“游戏性理解”上是三个人里最强的。4. 修 Bug 环节真正拉开差距的地方4.1 Step 5 Preview多轮修复几乎没引入新问题写代码只是第一步修 Bug 才是真正考验模型的环节。我在 Step 5 Preview 的代码里故意制造了几个问题删掉一个坐标轴上的摩擦力逻辑、把相机跟随的 Lerp 系数从 0.08 改成 1.0、把障碍物碰撞矩阵的某个索引改错。然后让它自己去跑、自己去修。结果是它的修复速度非常快而且每次只改动一处逻辑不会顺手把别的地方改坏。最让我满意的是它发现自己修改了 Lerp 系数之后不仅把系数改回来还额外修复了一个潜在问题相机在高速移动时会出现延迟抖动它建议把 Lerp 结果强制同步到当前帧位置。这个“主动发现潜在问题”的能力说明它对整体系统状态有持续追踪而不只是执行单条指令。4.2 DeepSeek V4 Pro修了 A 处坏了 B 处DeepSeek V4 Pro 的 Bug 修复过程就比较让人血压升高了。它修穿模问题时会把障碍物的碰撞半径调大 0.5结果导致小球离障碍物还很远就被弹开把它调小后又出现“跟没检测到一样”的穿模。这种“修一处、坏一处”的情况在多轮对话中出现了三次。我分析了一下深层原因它可能没有把“碰撞检测”当作一个整体系统来理解而是只针对当前报错位置做局部 patch。当代码变长以后这种“局部 patch”风格会让整个系统越修越乱。这时候如果再加一个“请一次性检查所有碰撞相关逻辑”的提示它的表现会好很多。所以 DeepSeek V4 Pro 更适合你明确指到“这里不对”而不是让它“自己检查哪里不对”。4.3 GLM5.3依赖强提示但“野路子”也能救场GLM5.3 修 Bug 的表现比较依赖提示词强度。给它一个模糊的“有点问题”提示它会东翻西找半天甚至开始重构无关代码给它一个明确的“小球从 x5 附近掉出平台请加边界检测”它能很快给出方案。有一次我测试小球掉出平台边界的问题它的修复方案非常“野”直接把所有非平台区域的地板都加上隐形碰撞盒形成一个“空气墙”。这个方案虽然粗暴但在 demo 场景里确实能解决问题而且性能损耗几乎可以忽略。这种“能救场就行”的思路我觉得也挺符合快速迭代的实际需求。4.4 顺带分享GLM5.3 本地部署的 vLLM 镜像选型测试过程中我还顺手在本地把 GLM5.3 部署了一遍结果发现网上一堆人问“glm5.3 使用 vllm 哪个版本的镜像”。这个坑我替你们踩过了。千万别直接沿用旧模型那套镜像配置我一开始用默认镜像时加载权重后出现 attention 算子和官方实现不匹配的报错位置编码也有偏差生成结果偶尔会出现重复片段。实测下来GLM5.3 镜像选型要看你用的是基础版还是 flashx 版。基础版对 vLLM 版本要求相对宽松但 flashx 版必须用比较新的 vLLM 发布版本旧镜像会直接提示算子不兼容。另外部署时记得看 FlashAttention 的版本如果 PyTorch 和 vLLM 的编译版本对不上报错会在 import 阶段就炸出来。有条件的话建议直接跑官方推荐的 docker 镜像别自己手动编译省下的时间够你多测三轮游戏。至于很多人拿 doubao-seed-2.0-code 跟 GLM5.3 比代码能力我这次没有让豆包进场但按照抖音那边公开的 benchmarks代码专项确实很强。这个等以后再开一场专门的对比今天先不掺和进来。5. 避坑指南给想复测的人几条实在建议5.1 提示词里一定要写“跑不起来怎么办”三个模型对比下来我最大的感受是提示词里的规则描述比“请写一个好游戏”重要得多。如果你只写“请开发一个 3D 游戏”大概率会收到一个视觉效果炫酷但逻辑稀碎的 demo。我上面那份提示词里加了“碰障碍物弹开并扣时间”“掉出平台失败”“首次运行无报错”这些规则直接决定了代码结构。尤其是“首次运行无报错”这六个字能触发模型自动逻辑检查比自己跑完再修省事得多。另外建议在提示词里加上“关键参数集中配置”这类表述。三个模型里只有 Step 5 Preview 是主动做了参数集中管理另外两个需要你额外要求才会做。不要让模型把数字埋在一堆函数中间。5.2 先看控制台不要只看画面测试 AI 生成的 3D 页面最容易犯的错就是“画面看起来正常就认为没问题”。实际上很多问题都藏在你没注意的地方自动旋转相机导致性能消耗无限增长、事件监听没有移除导致重复叠加、物体矩阵更新用错了更新标志导致碰撞盒与实际位置不一致。我的习惯是打开浏览器控制台把所有报错和警告拉出来看一遍。Three.js 有一个特性是很多 API 调错了不会抛异常只是在你不知情的情况下静默失效。比如Object3D的矩阵更新如果你改了 position 但没调用updateMatrix()渲染可能还是用的旧矩阵这种情况不报错但小球会卡在原地不动。看控制台的同时也要重点确认这些“静默失效点”。5.3 复测项目不要只看“第一次跑通”只跑一次就下结论对模型是不公平的。3D 项目最关键的是“改五轮需求之后还能不能保持稳定”。我这次测试的“重新开始”功能就是一个很好的试金石有的模型第一版能跑但 restart 之后计时器不归零有的模型 restart 之后障碍物消失了因为碰撞检测数组没有重新初始化。建议你复测时至少跑这三个动作正常通关一次、过程中故意掉出平台一次、通关后立刻点重新开始。这三个动作能覆盖大部分状态管理相关的雷区。说实话很多模型未必能扛住“重新开始”这一步。5.4 如果只选一个我现在的推荐逻辑很多人会问我“到底哪个模型最强”。我的回答是看你的定位。想要一个稳定的项目骨架、代码结构清晰、适合继续迭代Step 5 Preview 是首选。它的代码像是有经验的工程师写的而不是一个“写过很多开源项目但没做过游戏”的人写的。想要大而全、丰富度高、愿意接受二次调参DeepSeek V4 Pro 更适合。它的功能丰富度是真的强但你要做好修 Bug 时被它反复拉扯的心理准备。想要快速出 demo、玩创意、不在乎代码规范GLM5.3 是惊喜之选。它写出来的东西不一定完美但总能给你一个没想到的视角。这套对比不只适用于 3D 游戏放到其他复杂项目上也成立数据可视化、小工具开发、甚至是自动化脚本评判一个模型的标准永远是“改需求的时候它会不会崩”。最后再分享一个小技巧这类测试做完以后记得把三个模型生成的第一版代码各自存一份备份。我这次就是先跑 Step 5 Preview 生成的版本再把另外两个模型的代码分别放进同一个目录里做对比。这样能清楚地看到当代码风格、参数设计、模块划分完全不同时最终效果差距到底有多大。多存几个版本后面想复盘差异点时真的能省很多时间。