1. 三个模型同台做3D游戏,我为什么选了这个题目
最近圈子里讨论度最高的话题之一,就是几个主流大模型在代码生成上的正面对比。Step 5 Preview、DeepSeek V4 Pro、GLM5.3 这三个名字频繁出现在各种技术群里,但真正拿同一个项目去横向实测的内容并不多。大多数对比要么是跑个算法题,要么是写个单文件脚本,这种测试说实话参考价值有限——真实开发场景里,代码是跨文件、跨模块、有状态、有依赖的,单文件跑分高不代表能扛住一个完整项目。
我决定用一个3D游戏作为测试载体。原因很直接:3D游戏开发天然涉及多个技术维度——场景图管理、渲染管线、物理碰撞、输入系统、资源加载、状态机、UI叠加。它不像CRUD接口那样有固定套路,也不像纯算法题那样可以靠背模板得分。一个模型能不能把3D游戏做出来,能暴露出它在空间推理、数学计算、架构设计、调试能力上的真实水平。
这次实测的目标不是评出谁最强,而是搞清楚三件事:第一,每个模型在3D游戏这个场景下的能力边界在哪里;第二,它们各自擅长什么、容易在什么地方翻车;第三,如果你手头有类似需求,应该怎么选、怎么用。文章里会涉及大量实操细节和踩坑记录,适合正在做AI辅助开发、或者对模型代码能力评估感兴趣的读者。
提示:本文所有测试均在相同硬件环境和相同提示词条件下进行,尽量保证公平。但模型输出存在随机性,单次结果不代表绝对水平,建议结合自己的实际场景多做几轮验证。
2. 测试方案设计:为什么是3D游戏,为什么是这三个模型
2.1 3D游戏作为测试基准的合理性
选3D游戏做基准,不是因为它难,而是因为它"综合"。一个最小的可玩3D游戏,至少需要以下模块协同工作:
- 场景初始化:相机、光照、地面、天空盒
- 玩家控制:键盘输入映射、移动向量计算、相机跟随
- 物理系统:重力、碰撞检测、地面判定
- 游戏逻辑:得分、计时、胜负条件
- UI系统:分数显示、开始/结束界面
- 资源管理:模型加载、纹理绑定、音频播放
这些模块之间不是孤立的,它们通过状态和事件相互耦合。比如玩家移动会触发碰撞检测,碰撞结果会影响得分,得分变化要更新UI。模型如果只会写孤立函数,在这个场景下会立刻暴露问题——它可能写出一个能跑的移动逻辑,但和碰撞系统对不上;或者UI更新了但游戏状态没同步。
另外,3D游戏对数学的要求是实打实的。向量运算、矩阵变换、四元数旋转、射线检测,这些不是靠语言模型"感觉"就能写对的。一个模型如果对空间数学理解不到位,写出来的相机控制会出现万向节死锁,或者移动方向跟视角对不上。这种错误在2D场景里不明显,在3D里一测就现原形。
2.2 三个模型的定位差异
在开始之前,先简单说一下这三个模型在我实际使用中的定位感受,这会影响我对它们输出结果的预期和评判角度。
Step 5 Preview是这次实测里我接触最少的。从命名看它处于预览阶段,我预期它在某些能力上可能还没完全稳定,但往往预览版模型会在特定方向上做激进尝试。实际用下来,它在代码结构组织上有自己的思路,不是简单堆砌。
DeepSeek V4 Pro在代码生成领域口碑一直不错,尤其是长上下文和复杂逻辑处理。我之前的经验是它在算法实现和架构设计上比较稳,但有时候会过度设计,把简单问题复杂化。这次重点看它在3D这种需要精确数学的场景下表现如何。
GLM5.3是最近讨论度很高的版本,社区反馈它在代码理解和生成上有明显提升。我比较关注它在"一次成型"方面的能力——也就是能不能在较少迭代次数下产出可运行代码。3D游戏这种多模块项目,如果每次都要大量人工修补,实用性就会打折扣。
2.3 统一的测试流程
为了保证对比有意义,我采用了相同的测试流程:
- 统一提示词:用同一段自然语言描述游戏需求,不针对任何模型做提示词优化
- 统一运行环境:相同的浏览器版本、相同的本地服务器配置
- 统一评估维度:从可运行性、功能完整度、代码质量、迭代次数四个维度打分
- 记录完整过程:包括每次报错、每次修改、每次重新生成
提示词的核心内容是:做一个3D第一人称视角的收集类游戏,玩家在场景中移动,收集随机生成的道具,有时间限制和得分系统。技术栈限定为Three.js + 原生JavaScript,不依赖构建工具,直接浏览器打开可运行。
注意:限定技术栈很重要。如果不限定,模型可能选择它最熟悉的框架,导致对比失去意义。Three.js是目前最通用的Web 3D方案,对三个模型来说都是"公平赛道"。
3. Step 5 Preview 的实战表现:结构清晰但细节需要补
3.1 首次生成:架构意识在线
Step 5 Preview 第一次输出的代码让我有点意外。它没有把所有逻辑塞进一个文件,而是主动拆成了几个模块:
main.js:入口,负责初始化场景和启动游戏循环player.js:玩家控制器,包含移动和相机逻辑world.js:场景搭建,地面、光照、道具生成game.js:游戏状态管理,得分、计时、胜负判定
这种拆分方式说明它对项目结构有基本认知,不是单纯地"把代码写出来"。每个模块的职责边界也比较清晰,没有出现玩家控制器里去操作UI这种越界行为。
但问题出在模块之间的通信上。它用了全局变量来共享游戏状态,比如window.gameState。这种做法在小型项目里能跑,但扩展性很差。而且它没有处理模块加载顺序问题,如果浏览器缓存导致某个文件加载慢,初始化就会报错。
3.2 3D数学部分:基本正确但有隐患
玩家移动逻辑是3D游戏的核心。Step 5 Preview 用了标准的向量计算方式:
// 根据相机朝向计算移动方向 const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(camera.quaternion); const right = new THREE.Vector3(1, 0, 0).applyQuaternion(camera.quaternion); forward.y = 0; right.y = 0; forward.normalize(); right.normalize(); const moveDirection = new THREE.Vector3(); if (keys.w) moveDirection.add(forward); if (keys.s) moveDirection.sub(forward); if (keys.a) moveDirection.sub(right); if (keys.d) moveDirection.add(right); moveDirection.normalize();这段代码逻辑是对的,把y轴分量清零再归一化,避免了相机俯仰影响移动速度。但它漏了一个关键处理:当玩家同时按下W和S,或者A和D时,moveDirection会变成零向量,归一化时会产生NaN。虽然实际游戏中很少同时按相反方向键,但这是健壮性问题。
更隐蔽的问题在相机控制上。它用了欧拉角直接设置相机旋转:
camera.rotation.y -= mouseMovementX * sensitivity; camera.rotation.x -= mouseMovementY * sensitivity;这种写法在俯仰角接近正负90度时会出现万向节死锁,相机翻滚。正确做法是用四元数或者限制俯仰角范围。Step 5 Preview 没有做这个限制,实测中快速上下移动鼠标时相机确实会失控。
3.3 道具收集与碰撞:能用但不够精确
道具收集用的是距离检测:
const distance = player.position.distanceTo(item.position); if (distance < 1.5) { collectItem(item); }这种"球形碰撞"在大多数情况下够用,但视觉上会有偏差——玩家明明还没碰到道具,道具就消失了。更精确的做法是用包围盒检测或者射线检测。不过考虑到这是快速原型,这个精度可以接受。
真正的问题在于道具生成。它用了完全随机的位置:
const x = (Math.random() - 0.5) * 40; const z = (Math.random() - 0.5) * 40;但没有检查生成位置是否与障碍物重叠。实测中出现了道具生成在墙体内部的情况,玩家无法收集,导致游戏无法完成。这个bug在测试中触发了两次,说明不是偶发。
3.4 迭代修复:需要明确指令
针对上述问题,我给了Step 5 Preview 明确的修复指令。它的响应质量取决于指令的具体程度:
- 说"修复相机问题",它会重新生成整个相机控制代码,可能引入新问题
- 说"限制相机俯仰角在正负85度之间",它能精确修改对应代码
这说明它对模糊指令的处理能力有限,需要用户自己先定位问题。对于有经验的开发者这不是大问题,但对新手来说,可能不知道问题出在哪里,也就无法给出精确指令。
经过三轮迭代,Step 5 Preview 的版本达到了可玩状态。最终代码约450行,功能完整,但代码里还残留了一些未使用的变量和注释掉的调试代码。
4. DeepSeek V4 Pro 的表现:数学扎实但容易过度设计
4.1 首次生成:一次就跑起来了
DeepSeek V4 Pro 的首次输出是三个模型里唯一一个直接就能跑的。没有报错,没有缺失依赖,打开浏览器就能操作。这一点确实体现了它在代码生成上的成熟度。
它的代码组织方式和Step 5 Preview不同,用了类继承结构:
class GameObject { constructor(scene) { this.scene = scene; this.mesh = null; } update(deltaTime) {} } class Player extends GameObject { constructor(scene, camera) { super(scene); this.camera = camera; this.velocity = new THREE.Vector3(); this.setupControls(); } update(deltaTime) { this.handleMovement(deltaTime); this.updateCamera(); } }这种面向对象的结构在扩展性上更好,但代码量也更大。对于一个小型游戏来说,有点杀鸡用牛刀的感觉。
4.2 物理与碰撞:精度最高
DeepSeek V4 Pro 在碰撞检测上用了射线检测:
const raycaster = new THREE.Raycaster(); raycaster.set(player.position, new THREE.Vector3(0, -1, 0)); const intersects = raycaster.intersectObjects(groundObjects); if (intersects.length > 0) { player.position.y = intersects[0].point.y + playerHeight; this.velocity.y = 0; this.isGrounded = true; }这种写法比简单的距离检测精确得多,玩家不会穿模,也不会浮空。道具收集也用了包围球检测,但半径是根据道具模型的实际尺寸动态计算的,不是硬编码。
相机控制方面,它用了四元数来避免万向节死锁:
const quaternion = new THREE.Quaternion(); quaternion.setFromEuler(new THREE.Euler(pitch, yaw, 0, 'YXZ')); camera.quaternion.copy(quaternion);这是标准的第一人称相机实现方式,数学上没有问题。实测中相机控制非常顺滑,没有出现任何翻滚或抖动。
4.3 过度设计的代价:代码臃肿
DeepSeek V4 Pro 的问题不在功能,而在代码量。它实现了一个完整的事件系统、一个状态机、一个对象池来管理道具。这些在大型项目里是必要的,但在这个小游戏里显得冗余。
最终代码约1200行,是Step 5 Preview的三倍。其中真正核心的逻辑可能只有400行,其余都是框架代码。这导致两个问题:一是调试时需要在大量代码中定位问题,二是模型在后续迭代中容易改错地方——它可能会去修改事件系统的代码,而实际问题出在游戏逻辑里。
另外,它引入了一些不必要的依赖。比如用了一个第三方库来处理键盘输入,但这个库需要额外引入,增加了部署复杂度。虽然它自己在注释里说明了如何引入,但对于"直接打开浏览器就能跑"这个要求来说,多一步都是负担。
4.4 迭代体验:稳定但改动范围大
给DeepSeek V4 Pro提修改需求时,它的响应很稳定,不会引入新bug。但它的改动范围往往超出预期。比如我说"增加一个跳跃功能",它不仅加了跳跃,还重构了玩家状态管理,把原来的简单布尔值改成了状态机。功能是实现了,但代码变动太大,不利于版本对比。
实操心得:用DeepSeek V4 Pro做快速原型时,建议在提示词里明确限制代码规模,比如"用最少的代码实现,不要引入额外抽象"。否则它很容易把项目做成一个"框架"。
5. GLM5.3 的表现:平衡性最好但偶有惊喜和惊吓
5.1 首次生成:完成度最高
GLM5.3 的首次输出在功能完整度上是最好的。它不仅实现了所有要求的功能,还额外加了一些小细节:道具收集时的粒子效果、得分变化的动画、游戏结束时的渐隐过渡。这些不是必须的,但说明它对"游戏体验"有理解,不只是完成功能清单。
代码结构上,它采用了折中方案:比Step 5 Preview更模块化,比DeepSeek V4 Pro更精简。用了ES6模块语法,但没有引入类继承,而是用工厂函数和闭包来组织代码。最终代码约600行,可读性不错。
5.2 一个意外的亮点:自动处理了边界情况
GLM5.3 在道具生成时做了碰撞检查:
function generateItemPosition(existingItems, obstacles) { let attempts = 0; while (attempts < 50) { const pos = randomPosition(); if (!checkCollision(pos, existingItems) && !checkCollision(pos, obstacles)) { return pos; } attempts++; } return randomPosition(); // 兜底 }这个逻辑不是我在提示词里要求的,但它主动加了。这说明它在生成代码时会考虑"这段代码可能出什么问题",而不是只关注功能实现。实测中道具生成位置全部合理,没有出现无法收集的情况。
5.3 惊吓时刻:一次隐蔽的数学错误
但GLM5.3也犯了一个比较隐蔽的错误。在计算玩家移动速度时,它用了:
const speed = baseSpeed * deltaTime * 60;这个写法假设了帧率稳定在60fps。如果帧率波动,移动速度会不一致。正确做法是直接用deltaTime作为时间因子,不需要乘以60。这个错误在测试机上不明显(因为帧率稳定),但如果换到性能较差的设备上,玩家移动会变慢。
这个问题的隐蔽性在于:代码能跑,功能看起来正常,只有在特定条件下才会暴露。如果不是我特意检查了移动逻辑,可能就漏过去了。
5.4 迭代响应:精准且克制
GLM5.3 在迭代时的表现最好。给它指出问题后,它只修改相关代码,不会大范围重构。比如我指出速度计算问题,它只改了那一行,其他代码原封不动。这种克制在迭代开发中很重要,能减少引入新bug的概率。
另外,它对模糊指令的处理也比Step 5 Preview好。我说"相机感觉有点飘",它能理解到是灵敏度或平滑度的问题,主动调整了相关参数,而不是重新生成整个相机代码。
6. 三个模型的横向对比:数据说话
6.1 量化对比表
| 维度 | Step 5 Preview | DeepSeek V4 Pro | GLM5.3 |
|---|---|---|---|
| 首次可运行 | 否(需修复) | 是 | 是 |
| 首次功能完整度 | 70% | 95% | 100% |
| 最终代码行数 | ~450 | ~1200 | ~600 |
| 迭代到可玩次数 | 3次 | 1次 | 1次 |
| 3D数学正确性 | 基本正确,有边界问题 | 正确 | 正确,有一处隐蔽错误 |
| 代码可读性 | 良好 | 一般(过度抽象) | 良好 |
| 扩展性 | 一般 | 好 | 好 |
| 对模糊指令的处理 | 差 | 中 | 好 |
| 额外功能 | 无 | 无 | 粒子效果、动画 |
6.2 各自的能力边界
Step 5 Preview的边界在于细节处理。它能搭出正确的骨架,但在边界条件、异常处理上需要人工补全。适合有经验的开发者用来快速生成原型,然后自己打磨。
DeepSeek V4 Pro的边界在于"度"的把握。它的技术能力没问题,但容易把项目做重。适合中大型项目,或者你确实需要一个可扩展的架构时使用。做小项目时反而会增加负担。
GLM5.3的边界在于复杂数学场景。它在常规逻辑上表现很好,但在需要精确数学推导的地方可能出隐蔽错误。适合业务逻辑复杂但数学要求不高的场景,或者你需要快速产出可演示原型时使用。
6.3 一个有意思的发现:错误类型不同
三个模型的错误类型有明显差异:
- Step 5 Preview 的错误是"遗漏"——该处理的没处理
- DeepSeek V4 Pro 的错误是"过度"——不该处理的处理了
- GLM5.3 的错误是"近似"——用了看起来对但不够精确的方案
这个差异反映了它们训练数据和优化目标的不同。对使用者来说,了解这些倾向性比知道谁"更强"更有价值,因为你可以根据项目特点选择更匹配的模型,或者在提示词里针对性预防。
7. 实操建议:怎么用这三个模型做3D游戏
7.1 提示词里必须写清楚的几件事
不管用哪个模型,做3D游戏时提示词里一定要明确以下内容:
- 技术栈和版本:Three.js的版本不同,API差异很大。不指定版本,模型可能用已废弃的API。
- 运行方式:是直接浏览器打开,还是需要构建工具。这决定了模型是否可以使用模块导入。
- 代码规模限制:明确说"用最少的代码实现"或"允许使用面向对象结构",避免模型自由发挥。
- 边界条件要求:比如"道具不能生成在障碍物内部"、"相机俯仰角需要限制",这些如果不说,模型可能不会主动处理。
7.2 迭代时的沟通技巧
- 定位到具体文件和函数:不要说"移动有问题",要说"player.js里的handleMovement函数,当同时按下W和S时会产生NaN"。
- 一次只提一个需求:多个需求混在一起,模型可能只处理了其中一个,或者处理时相互干扰。
- 要求最小改动:明确说"只修改相关代码,不要重构其他部分",减少引入新问题的概率。
7.3 验收时要重点检查的地方
3D游戏有几个容易出问题但不容易发现的地方,验收时建议重点检查:
- 帧率无关性:移动、旋转、计时是否都用了deltaTime,而不是假设固定帧率
- 边界情况:同时按相反方向键、快速移动鼠标、道具生成在角落
- 内存泄漏:游戏结束后是否正确清理了事件监听和定时器
- 移动端兼容:如果需要在手机上运行,触摸控制和性能优化是否考虑到了
提示:建议在验收时用浏览器的性能面板录一段游戏过程,看看有没有帧率骤降或内存持续增长的情况。这些问题在短时间测试中不明显,但会影响实际体验。
8. 关于WorkBuddy等工具的一些实际体会
测试过程中,我也顺带用WorkBuddy做了一些辅助工作。这个工具在管理多轮对话和代码版本方面确实方便,尤其是需要同时跟三个模型对话时,它能帮你把每个模型的输出分开管理,不会混淆。
但有一点要注意:WorkBuddy的跨对话记忆功能在代码场景下需要谨慎使用。它可能会把上一个项目的上下文带入到新项目中,导致模型生成不相关的代码。我的做法是每个新项目都开一个新的工作区,不依赖跨对话记忆。
另外,WorkBuddy的自定义指令功能对代码生成有帮助。我设置了一条规则:"生成代码时优先考虑可读性,避免过度抽象"。这条规则对DeepSeek V4 Pro特别有效,能明显抑制它过度设计的倾向。
对于需要私有化部署的场景,WorkBuddy也支持本地运行,但配置过程比在线版复杂一些。如果只是做模型对比测试,在线版足够了。
9. 最后说几句实在的
这三个模型做3D游戏,没有一个是"完美"的。Step 5 Preview 需要你补细节,DeepSeek V4 Pro 需要你控制规模,GLM5.3 需要你检查数学。但它们的共同点是:都能在合理时间内帮你搭出一个可运行的原型,这比几年前从零手写已经快了很多。
我的实际用法是:用GLM5.3出第一版,因为它完成度最高、代码量适中;然后用DeepSeek V4 Pro检查数学和物理部分,把关键逻辑替换成更精确的实现;最后用Step 5 Preview做代码审查,它虽然自己写代码有遗漏,但检查别人代码时反而能发现一些被忽略的边界情况。
这个组合用法不一定适合所有人,但至少在我这几个项目里,效率比单用一个模型高不少。如果你也在做类似的事情,建议先明确自己的项目最看重什么——是快速出原型,还是代码质量,还是可扩展性——然后根据这个优先级去选择主力模型和辅助模型。