最近这几家模型打得是真热闹,Step 5 Preview 刚放出来,社区里就和 DeepSeek V4 Pro、GLM5.3 比来比去。老实说,大多数对比都停留在官网 Demo 或者刷榜单那种层面,动不动就是“code generation 能力提升 xx%”,说实话参考价值有限。我更好奇的是同一件事让三个模型从头写,谁的作品能直接打开、能玩、不出 bug。
所以这次我拉了个很“老土”但极其有效的测试题:让三个模型各自做一个 3D 小游戏。没错,就是那种直接跑在浏览器里、用 Three.js 搭的网页 3D 游戏。别小看这个选题,3D 游戏对模型的要求比普通的“写个网页”高一个量级,既要懂三维数学,又要懂物理碰撞,还要能把 UI、输入、循环逻辑捏成一个能玩的整体。这篇文章就把整个实测过程、代码偏析、部署相关的坑全部记录下来,不含糊。
1. 为什么拿 3D 游戏当试金石
1.1 三个模型这次对比的是“完整工程能力”
纯粹的语法题对现在这批模型已经没什么区分度了。你让它写个排序、写个二分查找,基本个个满分。真正拉开差距的是“从零搭一个完整可运行项目”的能力,尤其是那种涉及多个子模块、需要在脑子里维护一个全局状态的任务。
3D 游戏恰好是这种任务。它天然包含场景搭建、相机控制、渲染循环、用户输入、碰撞检测、计分逻辑、胜负条件这一整套链路。任何一个环节掉链子,最后都是“游戏打不开”或者“角色穿模穿到地心”这种致命问题。
另一个原因是 3D 游戏对“空间直觉”的考验。模型不是人,它不能真的“看见”画面,它只能靠矩阵和向量的运算去想象一个三维世界。能不能把相机 position 写对、能不能让角色按照世界坐标移动而不是屏幕坐标移动、能不能让碰撞盒和视觉模型对齐,这些细节最能暴露一个模型对三维空间的理解深度。相比写增删改查,这东西几乎没有糊弄空间。
1.2 “能打开”不等于“能玩”:测试标准
我看过太多 AI 生成的 3D 项目,很多是“能运行但完全不能玩”。怎么定义“能玩”很关键。所以我定的验收标准非常具体:
- 双击打开 HTML 就能看到场景,不需要起本地服务,不依赖任何脚手架
- 有完整的角色控制,键盘操作响应灵敏,不是反方向、不是漂移
- 场景里必须有明确的互动目标,这次是收集金币,碰到就消失、加分
- 有结束条件,收集完所有金币弹出胜利提示,而不是无限挂机
- 再来一条:代码不能臃肿到根本没法改,如果一个碰撞检测写了三百行,这项目的后期可维护性就归零了
这五条全部满足,才算合格。合格之后再谈代码风格、可读性、工程组织这些更高阶的东西。
2. 测试设计:一个提示,同一套规则
2.1 提示词怎么写才能公平对比
为了让三个模型输出有可比性,提示词必须完全一致。但这里有个容易被忽略的点:提示词太简单,比如“写个 3D 游戏”,模型会自行发挥,输出形态千差万别;提示词太细节,等于你替模型做了大部分决策,测不出模型的真实水平。
平衡点是“给出验收标准,但不给实现方案”。
我个人的习惯是把五个要素写进提示词,形成一套可复用的模板。角色与操作方式、场景与环境风格、核心玩法目标、计分与反馈、运行约束条件。这五个要素各写一句话,剩下的全交给模型自动发挥。
为什么这样设计?因为这套模板模拟的是真实开发场景里的需求沟通。没有一个靠谱的产品经理会写“给我做个游戏”,但一个合格的产品经理会把规则、交互、验收标准说清楚。技术在规则之上自行决策,这才看得出本事。
2.2 给三个模型的同一道考题
我最后使用的提示词是这样的,直接复制上来的:
请做一个可以直接运行的 3D 寻宝小游戏,使用 Three.js 库,单 HTML 文件, 不要使用 npm、不要依赖任何脚手架,双击 HTML 文件即可打开运行。 游戏要求: 1. 玩家使用 WASD 或方向键控制一个球形角色,在场景中移动; 2. 场景包含草地平面、天空、若干简单树木和石块,风格偏卡通; 3. 地面上随机放置 8 个金币,角色碰到金币后金币消失并加 10 分; 4. 页面左上角显示实时分数,以及“已收集/总数”的统计; 5. 收集全部 8 个金币后,弹出“你赢了”的提示; 6. 角色不能穿过树木和石块,需要实现简单的碰撞阻挡; 7. 使用 Three.js CDN 最新稳定版本,代码中写清版本号和引入方式。 请输出完整可运行的 index.html,并添加必要注释。注意第 6 条。碰撞阻挡是这次测试里最硬核的难点,也是后续三方拉开差距的地方。如果不做特别要求,很多模型会直接忽略碰撞逻辑,角色到处透传,视觉效果和工程完成度都会被大打折扣。
2.3 评测维度的选择
我并没有只凭“游戏能不能玩”一个维度打分。三个模型我都做了专项记录,重点盯五个维度:
| 评测维度 | 观察重点 |
|---|---|
| 可运行性 | 是否一次通过,有无控制台报错 |
| 规则遵循度 | 是否严格按提示词生成,如金币数量、计分规则 |
| 空间逻辑 | 移动方向、相机跟随、碰撞是否真实有效 |
| 代码组织 | 函数拆分、变量命名、是否便于二次修改 |
| 调试体验 | 出 bug 后,能不能快速定位到问题区域 |
为什么这么拆?因为这三个模型在“能不能跑”上八成都能过关,但“跑起来之后代码是不是人写的”“改起来顺不顺手”,这个差异只有在逐维度拆解的时候才能暴露出来。很多人说“A 比 B 强”,说来说去就是“A 生成的东西我能改,B 的我看不懂”,其实就是代码组织能力和可读性的差异。
3. 实测记录:三轮交手
3.1 第一轮:Step 5 Preview 的初稿
先跑的 Step 5 Preview。这个模型是最近热度上升最快的,讨论经常和 DeepSeek V4 Pro、GLM5.3 绑在一起,我想看的核心特色是它的整体布局能力和代码生成速度。
实际生成速度确实快,比另外两个几乎快了将近半分钟,响应体量也大。输入同一个提示词,它第一版就给出了完整的 index.html,约 400 行左右,不磨叽。
开门第一件事,把文件保存下来双击。结果浏览器控制台直接给我甩了个 Three.js 的版本警告,是因为它默认用了某个比较新的 CDN 版本,我本地浏览器的 WebGL 能力没啥问题,但版本里有个 API 已经标记为 deprecated。运行本身不报错,警告不影响逻辑,能跑。
实际体验下来,第一印象是“跑起来很直观”。镜头自动跟随小球角色的逻辑做得很顺滑,初始场景的草地和天空盒安排得很舒服,树木的摆放也没有明显的随机抖动。但这些表面功夫背后,我注意到一个问题:代码结构非常“平”。几乎是把所有逻辑从上到下拍成了一长条,没有把“场景构建”“角色控制”“碰撞检测”“计分系统”分模块组织。四百行代码里,改一个变量可能要顺着搜索字符翻几十处。
更典型的是它的碰撞逻辑。它为了解决“角色不能穿树”这个问题,直接拿角色中心到树干中心的距离做了个简单判断,完全没考虑树的实际几何尺寸。视觉效果是角色在树前面大概一个身位的地方就“被挡住”了,看着很违和。
第一轮的结论:Step 5 Preview 是一个“能迅速搭出大体框架”的选手,适合做激进原型,但它的代码从“能玩”到“能改”之间还有距离。
3.2 第二轮:DeepSeek V4 Pro 的教科书答案
接着上 DeepSeek V4 Pro。这家伙在第一轮就表现出了完全不同的气质。它没有在 HTML 里硬塞所有代码,而是先在注释里给了整个程序的逻辑大纲,然后按“场景初始化”“物理边界”“角色控制”“交互循环”几大块拆开写。变量的命名也很考究,playerRadius、coinGroup、obstacleList这类一眼能看懂的命名方式占绝大多数。
运行之后第一感觉是“稳”。没有版本警告,所有 API 用法都是保守的、稳定的写法,没有刻意追求新特性。角色移动手感是三个模型里最好的,移动时加了加速度和阻尼,不是那种瞬移式移动,也不是永远刹不住车。碰撞检测做得很扎实,它用一个通用的“圆形与矩形”碰撞检测函数,把所有树木和石块统一映射为可用的包围盒,角色被挡住的边界和视觉几乎完全贴合。
DeepSeek V4 Pro 对规则遵循度也最高。提示词说 8 个金币,它就生成 8 个,不多不少。计分逻辑、胜利判断、UI 提示位置,全都严格照做。
唯一让我觉得稍微“平淡”的是角色创意。它快速生成了所有要求的东西,没有多余的发挥,视觉效果中规中矩。这种“靠谱但不够惊艳”的风格,在工程化手里反而更吃香,因为你拿到的是一份可以直接进迭代的代码。
3.3 第三轮:GLM5.3 的稳健表现
最后跑 GLM5.3。这个模型的输出结构比较有意思,它的注释量极大,每个模块顶部都有一段中文说明,解释了这段代码的意图,甚至有些注释读起来像是在写技术文档。
实际效果方面,GLM5.3 的第一版就包含了相机跟随、角色碰撞、金币收集和胜利弹窗,机制层面没有缺项。它的视觉设计里多了一个加分项:场景中加了一层淡黄色的点状光照,让金币在旋转时有了高光反射效果。虽然这些都只是属性配置级别的改动,但至少说明模型知道“好看”是怎么构成的。
不过 GLM5.3 有一个在测试过程中显得很别扭的缺点。它的代码里大量使用了.clone(),每帧更新角色位置时都克隆一个新的 Vector3。这种写法在单独的 HTML 游戏里没什么大问题,性能损耗可以忽略,但一旦场景复杂或者需要多人、多角色,这种边执行边克隆的写法很容易带来大量临时对象,进而触发浏览器的内存抖动。也就是说,它对“当前场景”的优化很到位,但对“未来扩展”的预判不够。
还有一个细节,GLM5.3 的碰撞检测函数返回的不是碰撞点,而是一个简单的 bool。这就导致它虽然能阻止角色穿模,但无法处理“沿着障碍物滑动”的场景。角色撞到树之后会被硬生生卡住,按侧向键也不会擦着边缘滑过去,操作体验上差了一点。
3.4 增加跳跃键:一次 debug 测试
三个初版都通过之后,我又给每个模型追加了一个改动需求:“给角色增加空格跳跃能力,并按 2D 平面碰撞的方式让角色在 Y 轴上也能被障碍物阻挡。”
这是一个带陷阱的题。模型需要同时修改输入监听、角色速度状态机、碰撞逻辑,还要确保碰撞不会因为跳跃的加入而崩坏。
Step 5 Preview 最激进,直接改出了“跳跃 + 二次跳”,但它的碰撞更新函数把 Y 轴判断写错了一个符号,导致角色跳起来落地后,会陷入地面以下半个身位。
DeepSeek V4 Pro 采取的是“最小改动”策略。它把跳跃单独抽成一个状态变量,原有的碰撞检测函数对外接口不变,只是在需要的地方同步了 Y 轴坐标。改完立刻能跑,且没有引入任何新 bug。
GLM5.3 的改动是三个中最保守的。它完整保留原有逻辑,在外部加了一层“跳跃状态拦截”。代价是代码行数从 400 行涨到了 490 行,而且没有做特别的精简。
这轮综合下来:“Step 5 Preview”适合“大胆尝试但需要仔细验收”,因为它的改动是带有破坏性的;“DeepSeek V4 Pro”从稳定性和可维护性上胜出;“GLM5.3”则适合“不想冒任何风险”的场景,它宁可多写一点也不会大刀阔斧改结构。
4. 代码背后的性格:三个模型的底层差异
4.1 结构组织与可读性对比
同一个提示词,三个模型产出的代码风格差异之明显,让我产生了一种“像是在同时测试三个入职候选人”的错觉。
先看 Step 5 Preview。它的代码风格是:全部逻辑按顺序铺开,变量写在用到的位置旁边,没有函数级别的抽离。一个变量可能只在全局做了一次声明,后续所有逻辑共享。项目规模一旦上去,这种风格很容易让人无从下手。它在“快速验证”阶段的优越性是毋庸置疑的,但下游团队接手后,卖命的是读代码的人。
DeepSeek V4 Pro 的思路是“分层”。场景、逻辑、交互、工具函数都分得清清楚楚。狩猎时能一眼锁定问题所在,比如发现金币不减分,你直接去“scoreManager”区域找,根本不用把整个文件读完。这种组织能力其实是工程思维的体现,它知道真正的痛点永远在后期迭代,而不是第一版能跑不能跑。
GLM5.3 的特色是“注释驱动”。它几乎像是“先把设计文档写出来,再填充实现”。代码里的注释、函数命名、包含关系,已经接近一个初级工程师的上限。但对有经验的人来说,它的注释量稍显冗余,读代码时会被描述性注释分散注意力。它更像是一个“生怕你看不懂”的辅导型老师。
4.2 碰撞与空间逻辑:谁更像“会玩游戏”的人
3D 游戏里的碰撞检测,是所有 AI 模型最容易失控的地方,因为这里涉及到“隐式状态”。所谓隐式状态,是代码里没有直接声明,但从行为上能推断出的东西。比如一个角色移动了,它上一帧的位置、速度、加速度都不写在变量里,但逻辑依赖它们。模型能不能维护这种隐式状态,直接决定了它的空间判断力。
Step 5 Preview 的碰撞是最“表面”的,它直接把障碍物看成一个固定的圆形边界,角色碰线即停。这是一种“看起来没问题,但实际体验很粗糙”的解法。
DeepSeek V4 Pro 把碰撞检测做成了“基于速度向量求相交时间”的模式。角色每帧移动时,先计算它在当前速度下是否会撞上下一个障碍物,如果会撞,就在障碍物边缘停住。这个方案在工程上更“正宗”,因为它是从“物理引擎如何工作”的角度去设计的,后续加跳跃、加斜坡都比较平缓。
GLM5.3 则处在两者之间。它用的是一个实时距离判断,每帧计算角色到所有障碍物的距离,如果距离小于半径和障碍物半径之和,就朝反方向推。这种避免穿透的方式理解成本最低,但手感要差一点。
4.3 一个容易被忽略的维度:错误信息质量
我发现一个值得单列出来的差异——生成代码出错时,模型给的“报错解释”质量完全不同。
Step 5 Preview 遇到报错时,倾向于删除报错代码段直接重写,整体改动范围较大,有时会把原来写好的功能也一起抹掉。
DeepSeek V4 Pro 会在报错附近插入一个临时的调试输出语句,把关键变量的数值打印到控制台,再基于输出来做修复。这种“先诊断后动手”的思路,和专业开发者的排错习惯更像。
GLM5.3 则乐于保留原代码,在原函数旁边额外添加一个新的修复合函数,再用 if-else 从原逻辑分流出执行路径。结果是 bug 确实修好了,但整个函数的嵌套层级会快速膨胀。这种修复风格对“速度优先”的项目来说不是好习惯,因为函数深度超过两层后,输入输出的依赖关系很容易变成循环引用。
4.4 三个“代码指纹”辨识指南
在没有标注情况下,如果你同时打开三份代码,几乎不用看文件头就能判断出自哪家。
看到大段无模块化、勇猛直接的逻辑、变量偶尔会冒出tempVar、item01这类名字,八成是 Step 5 Preview 的产物。它有一种“我先推出来再想名字”的气质。
看到变量被分成常量区、角色区、组件区,每个函数头带着一两行复杂但准确的注释,核心逻辑通过模块间传递数据完成,这是 DeepSeek V4 Pro 的典型特征。
看到每段逻辑顶上都有类似中文功能摘要的注释、代码里频繁出现.clone()和临时变量、小修小补全用新函数来做,GLM5.3 的指纹基本没跑。
5. 部署与生态上的一些吐槽
5.1 GLM5.3 FlashX:速度优先的轻量方案
测试过程中看到社区里在聊 GLM5.3 FlashX,这里多说一句。FlashX 和完整版 GLM5.3 最大的区别是在“是否启用深度思考”上。FlashX 默认走的是快速推理路线,适用于那些不需要长时机决策的任务。比如重复代码生成、补全、格式整理这类任务,用 FlashX 性价比很高,响应速度快很多。
但如果你要做的是像这次测试这种“有明确空间逻辑、有交互状态、有完整需求”的项目,我还是建议直接用完整版。因为在 FlashX 模式下,模型倾向于“尽快给出一个看起来合理的答案”,对复杂约束的推演深度会明显变浅。你可以把它理解成一个“打字速度快但不太爱读题的助手”,适合做草稿,不适合直接进主干。
5.2 doubao-seed-2.0-code 与 GLM5.3 怎么选
这阵子 doubao-seed-2.0-code 也经常出现在和 GLM5.3 的横向对比里。如果只看这次 3D 游戏这一类前端任务,两者确实都能拿下,但核心取舍不太一样。
doubao-seed-2.0-code 的整体风格更偏向“高性能代码片段生成”,它擅长的是引擎内更密集的算法逻辑、复杂数据处理这一类干活很猛的任务。而 GLM5.3 在这次测试里表现出的强项,是“需求理解 + 完整项目组织”,它更适合负责一个跨模块的完整工程文件。你手里如果是一堆散落的小函数要快速补全,doubao-seed-2.0-code 更值;如果你要的是从一个提示词到一份独立可运行的项目,GLM5.3 的可用性会更高。
5.3 GLM5.3 用 vLLM 部署,镜像版本怎么选
因为这次测试的代码量不小,我也顺便想复刻一个本地环境再跑一轮,结果又撞上了那个每个部署人都要经历的问题:GLM5.3 用 vLLM 部署,到底该用哪个镜像版本。
从这个关键词的热度就能看出来,这问题不止我一个遇到。GLM5.3 这批模型在推理侧引入了更细粒度的 MoE 结构和新的注意力实现,对 vLLM 的调度器版本要求比较敏感。如果直接用旧的 vLLM 镜像去加载权重,最常见的报错是类似shape mismatch或者unsupported dtype,这类错误在旧版本 VLLM 中几乎无解,因为没有对应的算子支持。
我的建议是别图省事。如果你用官方镜像,先确认镜像发布日志里是否已经支持了 GLM5.3,尤其是要求 vLLM 版本大于等于某个新版本线,这个信息在官方模型仓库的 README 里通常有明确标注。
另外提醒一下,开启torch.compile时不要直接照搬早年的优化参数。GLM5.3 的 MoE 层在编译图模式下容易炸显存,建议先用非图模式验证推理链路正确,再做性能优化。这一步很多部署贴没写到,实际操作里特别容易卡壳。
6. 三轮实测下来,踩过的坑和排查思路
6.1 新手最容易踩的 6 个坑
这个项目虽然只有几百行代码,但短短两天里我踩了不少坑。整理成表,放在下面。这六条是最容易复现和困扰人的问题。
| 现象 | 可能原因 | 处理思路 |
|---|---|---|
| 双击 HTML 打开后画面全黑 | Three.js 版本过旧或过新不兼容 WebGL 上下文 | 检查控制台报错,锁定版本号手动指定稳定版本 |
| 角色移动方向和按键相反 | 模型把相机局部坐标和世界坐标混淆了 | 检查移动增量是在camera局部空间还是scene世界空间 |
| 金币碰了不消失 | 碰撞检测只判断了 X/Y 而漏了 Z 轴 | 检查碰撞函数是否覆盖三个维度,别只看二维投影 |
| 角色穿模卡进地面 | 跳跃落地后 Y 轴坐标没有归位到地面高度 | 每次落地后手动设置position.y = 0兜底 |
| 游戏运行 10 秒后画面越来越卡 | 渲染循环里不断创建新对象且未释放 | 使用对象池,或复用临时变量 |
| 弹出的“你赢了”反复触发 | 胜利判断没有加一次性标志位 | 用hasWon布尔变量做一个状态锁 |
这些坑看着都细小,但每条背后都对应着一个模型能力的短板。比如移动方向反,本质上是模型对“相机局部坐标和世界坐标转换”理解不到位;胜利弹窗反复触发,是模型在状态机设计上缺少一个基础的“一次触发”意识。
6.2 一套通用的 AI 代码排查流程
如果你也打算让模型生成整个 3D 项目,建议按这套流程来验收,能在几分钟之内把大问题压到可控范围。
第一步,先跑起来。任何 AI 生成的代码,第一件事永远是双击打开,或者本地起个静态服务,看控制台有没有报错。先不要看功能,只看运行。
第二步,强行触发交互。手动点击页面空白处、拖拽、缩放、按所有键位,把模型没预料到的用户输入全部尝试一遍。AI 出的代码往往在“预期路径”上没问题,但一碰到预期之外的输入,比如点击一下页面后角色瞬间漂移,这种问题就出来了。
第三步,改一个变量看效果。这是最有效的行为验证。你把金币数量从 8 改成 3,如果计分和胜利条件依然正确,说明逻辑是解耦的;如果一改就崩,说明功能之间强耦合,后续迭代成本会非常高。
第四步,检查注释和命名。这个很多人忽略,但非常重要。如果生成的代码注释全是废话,比如“// 设置x坐标”“// 创建球体”,说明模型只是在机械地填充代码片段的描述,而不是在理解逻辑脉络。真实项目里,这种代码维护起来最痛苦。
第五步,把报错贴回去重新生成。不要手工去改 AI 代码里的细节,除非你已经完全定位到问题。把控制台报错完整复制,连同“把这段代码改成不报错的版本”一起发回模型,它在上下文里保留对整体结构的理解,改动方案往往更合理。
6.3 一个额外的经验:同一份代码不要只测一遍
最后提醒一个很多评测不做的环节。同一条提示词跑一个模型,它每次生成的代码可能差异巨大。我在测试中让 Step 5 Preview 连续生成了三次,第一次是一套几乎全原创的方案,第二次看起来像是直接复用了搜索相似项目里常见的结构,第三次变成了“一版缩略版本”。
也就是说,如果你只跑一次就下结论,很容易低估或高估一个模型。正确的评估方式是在同一提示词下至少重复三轮,去看稳定输出水平,而不是看最好或最差的单次输出。这次测试我对每个模型都跑了三轮,三轮取中间水平作为对比基准。这才是我对这篇文章结论的信心来源。
关于选型,我现在的倾向已经比较固定了。如果是纯原型验证、一天之内就要出效果、不打算长期维护,Step 5 Preview 的生成速度和自由度是最大的;如果是要放进正式项目、后续还要反复迭代、团队其他人也会接手读代码,DeepSeek V4 Pro 的工程规范和稳定性是三个里最舒服的;如果你的需求是明确完整、不追求花哨、希望模型多帮你考虑边界情况,GLM5.3 会让你省心很多。
最后再分享一个写提示词的小技巧。不要把“做一个 3D 游戏”当作诉求丢给模型,而要写清楚“游戏必须能玩、能计分、有结束条件、打开就能运行”这四件事。这四件事在提示词里一旦说透,生成的代码质量会有明显提升。AI 编码类的工具本质上还是根据输入的自由度来分配它的“聪明程度”,你约束得越具体,它就越少走弯路。