三大代码模型实测3D游戏开发:Step 5、DeepSeek V4、GLM5.3谁更强? 1. 三个模型同台做3D游戏我为什么选这个题最近圈子里讨论度最高的一件事就是几个主流代码大模型在同一类任务上的横向对比。Step 5 Preview、DeepSeek V4 Pro、GLM5.3 这三个名字被反复提起但真正把它们拉到同一个项目里跑一遍的人并不多。多数评测要么是刷算法题要么是写个CRUD接口这类任务对模型来说太舒适了看不出真实差距。我选3D游戏作为测试场景理由很直接3D游戏开发是一个典型的多约束耦合任务。它同时涉及数学向量、矩阵、四元数、图形学渲染管线、光照模型、工程架构场景图、组件系统、以及大量琐碎的API调用。任何一个环节理解不到位代码就跑不起来而且报错信息往往指向不明。这跟写业务代码完全不同——业务代码写错了顶多逻辑不对3D游戏写错了是整个画面黑屏或者物体飞到无穷远。另外3D游戏有一个天然的优势结果可视化。你不需要去读代码判断对错跑起来看一眼就知道行不行。模型说它实现了第三人称相机跟随那相机到底跟没跟、跟得顺不顺、有没有穿墙画面上一目了然。这种即时反馈让评测变得非常客观。这篇文章我会完整还原整个实测过程从任务设计、环境搭建、三个模型各自的表现到最终跑通一个可玩的3D小游戏。中间踩的坑、发现的规律、以及关于用AI做3D游戏到底靠不靠谱的真实结论都会写清楚。如果你正在考虑用代码模型辅助游戏开发或者单纯想知道这几个模型在复杂任务上的真实水平这篇应该能给你一些参考。需要提前说明的是我用的都是各模型公开可用的版本测试环境统一prompt统一评判标准统一。不存在偏袒谁的问题好就是好拉胯就是拉胯。2. 任务拆解一个最小可玩3D游戏到底需要什么2.1 为什么我选第三人称收集类玩法市面上的3D游戏类型太多了FPS、RPG、沙盒、竞速每种对技术栈的要求都不一样。如果选FPS那核心难点在射击判定和网络同步如果选沙盒那核心难点在体素渲染和地形生成。这些都会把评测带偏——我想测的是模型对3D开发通用能力的掌握而不是某个细分领域的专精。最后我选了第三人称收集类玩法具体规则是玩家控制一个角色在3D场景中移动场景里随机分布若干可收集物品玩家靠近后自动拾取全部收集完则游戏胜利。这个玩法足够简单简单到任何一个有3D开发经验的人都能在几小时内手搓出来但它又足够完整完整到涵盖了3D游戏开发的几乎所有基础模块。具体来说它需要以下能力场景搭建创建地面、放置物体、设置光照角色控制键盘输入映射、角色移动、朝向旋转相机系统第三人称跟随、平滑插值、视角控制碰撞检测角色与地面、角色与收集物的碰撞游戏逻辑收集计数、胜利判定、UI显示动画系统角色移动动画、收集物旋转动画这六个模块缺一不可而且它们之间有依赖关系。比如相机跟随依赖角色位置碰撞检测依赖角色移动UI显示依赖收集逻辑。模型必须理解这些依赖才能写出能跑的代码。2.2 技术栈选择为什么是Three.js而不是Unity这里要做一个关键决策用引擎还是用库。Unity、Unreal这类完整引擎功能强大但它们的工作流是编辑器操作脚本编写模型没法操作编辑器只能生成脚本。这就导致模型生成的代码必须依赖一个已经配置好的场景而场景配置本身是模型看不到的。这会让评测变得不公平——模型可能代码写对了但因为场景没配好而跑不起来。Three.js是一个Web端的3D库它的特点是一切皆代码。场景、相机、光照、物体全部用JavaScript创建。这意味着模型生成的代码是自包含的复制粘贴到一个HTML文件里就能跑。这种特性让评测变得干净利落代码对不对跑一下就知道。而且Three.js的API设计比较直观文档也全模型在训练数据里见过的概率高。这对三个模型来说是公平的大家都有机会学好。提示如果你自己想做类似的评测强烈建议选代码即全部的技术栈。任何需要外部配置的工具都会引入噪音让评测结果不可信。2.3 我如何设计Prompt保证公平Prompt的设计直接决定评测的有效性。我见过太多评测给模型A的prompt写得详细给模型B的prompt写得简略然后得出结论说A比B强这没有意义。我的做法是写一个需求文档式的prompt包含以下要素项目目标一句话说清楚要做什么技术栈指定Three.js版本号写清楚功能清单逐条列出必须实现的功能交互说明键盘按键映射、鼠标操作视觉要求场景风格、配色倾向交付形式单个HTML文件可直接打开运行这个prompt对三个模型完全一致一字不差。我不做任何针对模型特点优化prompt的操作因为那会引入主观偏差。另外我要求模型输出完整的、可直接运行的代码而不是代码片段。这很重要——片段看起来都对拼起来可能全是问题。完整代码能暴露模型对整体架构的把握能力。3. 三个模型的首次输出谁在裸泳一目了然3.1 Step 5 Preview结构最完整但有个致命疏忽Step 5 Preview给我的第一印象是像个有经验的开发者。它输出的代码有清晰的模块划分用注释标出了每个部分的功能变量命名也规范。场景搭建部分它用了PlaneGeometry做地面用BoxGeometry做收集物光照用了AmbientLight加DirectionalLight的组合这些都是标准做法。角色控制部分它写了一个updatePlayer函数里面处理键盘输入、计算移动向量、更新角色位置。相机跟随它用了lerp插值让相机平滑跟随而不是硬跟。这些细节说明它确实理解第三人称相机的常见做法。但它犯了一个致命错误没有处理delta time。它的移动逻辑是player.position.x speed这里的speed是一个固定值。这意味着游戏速度会跟帧率绑定——在60帧的机器上角色移动速度是30帧机器的两倍。这是一个新手常犯的错误但在一个资深输出的代码里出现有点意外。另外它的碰撞检测写得很粗糙只是简单判断了距离没有考虑角色和收集物的实际尺寸。这导致收集判定有时候会隔空触发玩家还没碰到物品就被收集了。3.2 DeepSeek V4 Pro逻辑最严谨但代码风格偏学术DeepSeek V4 Pro的输出明显更学院派。它一上来就定义了一个GameState对象来管理游戏状态把所有可变数据集中管理。这种做法在大型项目里是好的但对于一个单文件小游戏来说有点过度设计。它的亮点在于数学处理。角色移动它用了向量运算相机跟随它用了四元数来做旋转插值碰撞检测它用了AABB轴对齐包围盒算法。这些都是3D开发里的标准做法说明它对底层原理掌握得不错。delta time它处理了用的是clock.getDelta()这是Three.js的标准做法。收集判定它用了包围盒相交检测比Step 5 Preview的距离判断准确得多。但它的代码有个问题可读性差。变量名用了很多缩写比如camOff、colBox、tmpV读起来费劲。而且它没有写注释整个代码块是一大坨想改点什么得先花时间理解。还有一个细节它用了OrbitControls来做相机控制但OrbitControls是轨道控制器适合观察场景不适合第三人称跟随。这说明它对Three.js的生态了解不够细知道有这个工具但没搞清楚适用场景。3.3 GLM5.3平衡性最好但细节有瑕疵GLM5.3的输出介于前两者之间。它的代码结构清晰注释适量变量命名规范读起来舒服。delta time处理了碰撞检测用了包围盒相机跟随用了插值该有的都有。它的特色是加了一些体验优化。比如收集物它会做上下浮动和旋转的动画让场景不那么死板收集时它会触发一个缩放消失的动画而不是直接删除UI它会显示已收集 X / Y的进度。这些细节说明它在做一个好玩的游戏而不只是完成功能。但它也有瑕疵。它的相机跟随在角色转向时会有抖动原因是它在计算相机位置时用了角色的世界坐标但没有考虑角色旋转带来的偏移。这个问题在角色直线移动时看不出来一转向就暴露了。另外它的键盘输入处理有个bug同时按下多个方向键时角色会斜向移动但速度没有归一化导致斜向移动比直线移动快。这是一个经典的向量归一化问题说明它在数学细节上不够严谨。3.4 首轮对比小结维度Step 5 PreviewDeepSeek V4 ProGLM5.3代码结构清晰模块化严谨但过度设计平衡易读数学处理一般有delta time疏漏强向量/四元数/AABB中等有归一化bug碰撞检测粗糙距离判断准确AABB准确包围盒相机系统平滑插值但转向有隐患用错控制器有抖动体验细节少少多有动画和UI可运行性能跑但速度异常能跑但相机不对能跑但有抖动首轮下来三个模型都能生成看起来像那么回事的代码但都有各自的问题。没有一个能直接交付。这说明当前代码模型在3D游戏这种复杂任务上还处于能帮你写初稿但需要你把关的阶段。4. 逐轮迭代把三个模型的代码揉成一个能玩的版本4.1 第一轮修复delta time和向量归一化首轮代码的问题里最影响体验的是两个Step 5 Preview的帧率绑定和GLM5.3的斜向加速。这两个问题都属于基础不牢但修复起来不难。delta time的修复方案是引入一个时钟每帧计算距离上一帧的时间差然后把这个时间差乘到速度上。Three.js里用THREE.Clock就行const clock new THREE.Clock(); function animate() { requestAnimationFrame(animate); const delta clock.getDelta(); updatePlayer(delta); renderer.render(scene, camera); } function updatePlayer(delta) { const speed 5; // 单位米/秒 // 移动逻辑 player.position.x moveX * speed * delta; player.position.z moveZ * speed * delta; }这样无论帧率是30还是144角色移动速度都是每秒5米体验一致。向量归一化的修复更简单。当玩家同时按下W和D时移动向量是(1, 0, 1)长度是根号2约1.414。如果不归一化斜向移动速度就是直线移动的1.414倍。修复方法是把移动向量除以它的长度let moveX 0, moveZ 0; if (keys[w]) moveZ - 1; if (keys[s]) moveZ 1; if (keys[a]) moveX - 1; if (keys[d]) moveX 1; // 归一化 const length Math.sqrt(moveX * moveX moveZ * moveZ); if (length 0) { moveX / length; moveZ / length; }这两个修复加起来不到20行代码但体验提升是巨大的。这也说明一个道理3D游戏开发里数学细节决定手感。4.2 第二轮修复相机跟随的抖动和穿墙相机问题是三个模型都没处理好的。Step 5 Preview的相机在角色转向时会滞后DeepSeek V4 Pro用错了控制器GLM5.3的相机有抖动。我最后采用的方案是弹簧臂式相机。原理是相机不直接跟随角色而是跟随一个目标点这个目标点在角色后上方。相机位置用插值慢慢靠近目标点这样既有跟随感又不会抖动。// 计算相机目标位置 const cameraOffset new THREE.Vector3(0, 3, -5); const targetPosition player.position.clone().add(cameraOffset); // 平滑插值 camera.position.lerp(targetPosition, 0.1); // 相机看向角色 camera.lookAt(player.position);这里的0.1是插值系数越大跟随越快但越容易抖越小越平滑但越滞后。我试下来0.1到0.15之间比较合适。穿墙问题更复杂一些。简单做法是发射一条从角色到相机的射线如果射线碰到墙壁就把相机拉到碰撞点前面。Three.js的Raycaster可以做这件事const raycaster new THREE.Raycaster(); const direction camera.position.clone().sub(player.position).normalize(); raycaster.set(player.position, direction); const intersects raycaster.intersectObjects(walls); if (intersects.length 0) { const distance intersects[0].distance; camera.position.copy(player.position).add(direction.multiplyScalar(distance * 0.9)); }这个方案不是完美的但在小场景里够用。真正的商业游戏会用更复杂的碰撞体检测但那是另一个话题了。4.3 第三轮修复碰撞检测的精度问题Step 5 Preview的距离判断太粗糙我换成了包围盒检测。Three.js里每个Mesh都有一个geometry.boundingBox可以用来做AABB检测function checkCollision(obj1, obj2) { const box1 new THREE.Box3().setFromObject(obj1); const box2 new THREE.Box3().setFromObject(obj2); return box1.intersectsBox(box2); }这个方案比距离判断准确但有个性能问题每帧都要重新计算包围盒。对于小场景几十个物体没问题物体多了就要用空间分割优化。不过对于我们的收集类游戏物体数量不多直接算就行。收集判定我用的是角色包围盒与收集物包围盒相交相交就触发收集。这样玩家必须真正碰到物品才能收集不会隔空触发。4.4 最终版本的架构梳理经过三轮修复最终版本的结构是这样的场景层地面、墙壁、光照、收集物角色层角色模型、移动逻辑、动画相机层弹簧臂跟随、穿墙检测逻辑层碰撞检测、收集判定、胜利判定UI层进度显示、胜利提示整个代码大概400行单个HTML文件打开就能玩。三个模型的代码我都参考了Step 5 Preview的结构、DeepSeek V4 Pro的数学、GLM5.3的体验细节。最终版本是三者优点的融合。5. 实测中暴露的模型能力边界5.1 模型擅长什么样板代码和API调用三个模型在样板代码上的表现都很好。什么是样板代码就是那些有固定套路、不需要太多思考的部分。比如创建场景、创建相机、创建渲染器、设置光照这些代码在Three.js文档里都有示例模型见过无数次生成起来毫不费力。API调用也是模型的强项。new THREE.Mesh(geometry, material)、scene.add(object)、renderer.render(scene, camera)这些调用模型写得又快又准。这说明模型对Three.js的API掌握得不错至少常用的部分没问题。还有一个意外发现模型在命名上表现很好。变量名、函数名、类名都起得像模像样。这说明模型不仅学了语法还学了代码风格。5.2 模型不擅长什么跨模块的状态管理和边界条件模型真正拉胯的地方是跨模块的状态管理。3D游戏里角色位置、相机位置、收集物状态、游戏进度这些数据是相互关联的。角色移动了相机要跟着动收集物被收集了进度要更新进度满了游戏要结束。这些关联关系模型经常处理不好。具体表现是模型会把每个模块单独写对但模块之间的胶水代码经常出问题。比如Step 5 Preview的角色移动写对了相机跟随也写对了但相机跟随用的是角色的旧位置导致相机总是慢半拍。这就是状态同步的问题。边界条件也是重灾区。角色走到场景边缘会怎样收集物被收集后从数组里删除了但渲染循环还在引用它会怎样同时收集两个物品进度会不会加两次这些边界情况模型很少主动考虑需要人工补上。5.3 一个反直觉的发现模型越自信越容易出错测试过程中有个有意思的现象模型在它熟悉的领域反而更容易出错。比如DeepSeek V4 Pro对数学很自信用了四元数做相机旋转但四元数的乘法顺序它搞错了导致相机旋转方向反了。反而是它不太自信的地方比如UI显示它写得很保守没出问题。这个现象的解释是模型在熟悉领域会过度发挥用一些高级技巧但高级技巧的细节它没完全掌握就翻车了。在不熟悉领域它会保守发挥用最基础的写法反而稳。这对我们的启示是用模型写代码时不要被它的自信迷惑。它写得越花哨你越要仔细检查。5.4 关于模型能不能独立做3D游戏的结论直接说结论目前还不能。三个模型没有一个能一次性生成可玩的3D游戏。它们能生成看起来像那么回事的代码但都有各种问题需要人工修复。修复的工作量大概相当于自己写的一半。但这不意味着模型没用。模型的价值在于帮你跳过最枯燥的部分。场景搭建、API调用、样板代码这些占开发时间的一半以上模型能帮你省掉。你只需要专注于逻辑和体验这部分才是真正需要人的地方。所以正确的用法是把模型当高级代码补全而不是独立开发者。你负责架构和逻辑模型负责填充细节。这个分工下效率提升是明显的。6. 如果你想自己复现这套流程6.1 环境准备和最小依赖复现这套流程不需要复杂的环境。你只需要一个现代浏览器Chrome、Firefox、Edge都行一个文本编辑器VS Code、Sublime、甚至记事本一个本地服务器可选但推荐Three.js可以通过CDN引入不需要npm安装。在HTML里加一行script srchttps://cdn.jsdelivr.net/npm/three0.160.0/build/three.min.js/script版本号建议锁定不要用latest因为Three.js的API在不同版本间有变化模型生成的代码可能基于旧版本。本地服务器的作用是避免跨域问题。如果你只是加载本地模型文件直接双击HTML可能不行需要起一个服务器。Python自带的http.server就够python -m http.server 8000然后浏览器访问http://localhost:8000就行。6.2 给模型的Prompt模板如果你想让模型帮你写3D游戏代码prompt可以这样写请用Three.js版本0.160.0写一个第三人称收集类3D游戏要求 1. 场景一个20x20的地面四周有墙壁场景中有10个可收集的金色方块 2. 角色一个胶囊体用WASD控制移动移动方向相对于相机 3. 相机第三人称跟随鼠标控制视角旋转相机不能穿墙 4. 收集角色碰到方块则收集方块消失UI显示进度 5. 胜利收集全部方块后显示胜利提示 6. 交付单个HTML文件可直接打开运行 请输出完整代码不要省略任何部分。这个模板的关键是具体。不要说做一个好玩的游戏要说清楚场景多大、几个物体、什么颜色、什么交互。模型对具体的需求响应更好。6.3 代码审查的检查清单模型生成的代码我建议按以下清单检查[ ] delta time是否处理搜索getDelta或clock[ ] 向量是否归一化搜索移动逻辑里的除法[ ] 相机是否平滑搜索lerp或插值[ ] 碰撞检测是否准确看用的是距离还是包围盒[ ] 边界条件是否处理角色出界、物体删除后的引用[ ] 内存是否泄漏事件监听是否移除、对象是否dispose这个清单能帮你快速定位大部分问题。我实测下来模型代码的问题80%都在这几条里。6.4 迭代节奏的建议不要指望一轮就搞定。我的经验是至少三轮第一轮让模型生成初稿跑起来看能不能运行。这一轮的目标是能跑不追求完美。第二轮修复明显的问题比如速度异常、相机抖动、碰撞不准。这一轮的目标是能玩。第三轮优化体验加动画、加音效、调手感。这一轮的目标是好玩。每一轮之间把问题整理清楚再喂给模型。不要说游戏有问题帮我改要说角色斜向移动比直线快因为移动向量没有归一化请修复。具体的描述能让模型更准确地定位问题。7. 关于WorkBuddy这类工具在游戏开发中的实际定位热词里出现了不少WorkBuddy相关的内容我顺带聊一下这类工具在3D游戏开发里的实际作用。WorkBuddy这类工具的核心价值是工作流管理它帮你把任务拆解、进度跟踪、代码审查这些环节串起来。在3D游戏开发里它的用处主要体现在两个地方一是任务拆解。3D游戏开发涉及模块多容易乱。用WorkBuddy把场景搭建角色控制相机系统拆成独立任务逐个击破比一锅炖要清晰得多。而且每个任务可以单独交给模型处理上下文更聚焦生成质量更高。二是跨对话记忆。3D游戏开发周期长今天写的代码明天可能就忘了细节。WorkBuddy的跨对话记忆功能可以帮你保留关键决策比如为什么选AABB而不是球体检测相机插值系数为什么是0.1这些决策记录对后续维护很重要。但要说清楚一点WorkBuddy不能替代你对3D开发的理解。它是个管理工具不是技术工具。你得先知道3D游戏怎么做才能用好它。指望它帮你自动做游戏是不现实的。另外热词里提到的给WorkBuddy定几条规则后续对所有任务都生效这个功能在游戏开发里挺实用。你可以定几条规则比如所有代码必须处理delta time所有向量运算必须归一化所有对象删除后必须dispose让WorkBuddy在每次生成代码时自动检查。这能帮你避免很多低级错误。至于WorkBuddy的安装、配置、缓存目录这些属于工具使用层面的事跟3D游戏开发本身关系不大这里就不展开了。核心观点是工具是辅助技术是根本。8. 我踩过的几个坑和对应的解法8.1 模型生成的Three.js版本和CDN版本不匹配这个坑我踩了两次。模型生成的代码用了THREE.Geometry但Three.js在r125版本之后就把Geometry废弃了改成了BufferGeometry。结果代码跑起来报错说THREE.Geometry is not a constructor。解法是在prompt里明确指定版本号并且在HTML里锁定CDN版本。如果模型还是用了废弃API手动替换成新API。Geometry换成BufferGeometryFace3换成BufferAttribute这些替换有固定套路查一下文档就行。8.2 模型对相对相机移动的理解经常出错第三人称游戏里按W应该是向屏幕前方移动而不是向世界坐标的Z轴负方向移动。这个区别在相机旋转后特别明显。模型经常把两者搞混生成的角色移动方向跟相机不对应。解法是在移动逻辑里把输入向量从相机空间转换到世界空间。具体做法是用相机的旋转矩阵乘输入向量const inputVector new THREE.Vector3(moveX, 0, moveZ); inputVector.applyQuaternion(camera.quaternion); inputVector.y 0; // 保持水平移动 inputVector.normalize();这样无论相机怎么转按W都是向屏幕前方移动。8.3 收集物删除后的引用问题模型生成的收集逻辑经常是检测到碰撞从场景里移除物体从数组里删除。但渲染循环里可能还在引用这个物体导致报错。解法是删除物体时不仅要scene.remove(object)还要object.geometry.dispose()和object.material.dispose()释放内存。同时把数组里的引用也删掉。如果用了requestAnimationFrame确保循环里检查物体是否存在。function collectItem(item) { scene.remove(item); item.geometry.dispose(); item.material.dispose(); const index items.indexOf(item); if (index -1) items.splice(index, 1); }8.4 模型写的UI在窗口缩放时会错位模型生成的UI经常用绝对定位窗口一缩放就错位。解法是用CSS的flex布局或者相对单位或者干脆用Three.js的Sprite做3D UI。对于简单的进度显示用HTML覆盖层加CSS就行#ui { position: fixed; top: 20px; left: 20px; color: white; font-family: sans-serif; pointer-events: none; }pointer-events: none很重要不然UI会挡住鼠标操作。8.5 性能问题模型不知道什么时候该优化模型生成的代码经常有性能隐患。比如每帧都创建新的Vector3对象导致垃圾回收频繁触发。或者每帧都重新计算包围盒浪费CPU。解法是把不变的对象提到循环外面用对象池复用可变对象。比如// 不好每帧创建新对象 function update() { const direction new THREE.Vector3(1, 0, 0); // ... } // 好复用对象 const direction new THREE.Vector3(); function update() { direction.set(1, 0, 0); // ... }这个优化在物体少的时候看不出差别物体多了就是帧率的分水岭。9. 最后聊聊我对AI做游戏这件事的真实看法跑完这轮实测我对AI做游戏的认知清晰了不少。短期内AI不可能独立做出商业级3D游戏。商业游戏的复杂度不是生成代码能解决的它涉及美术、音效、关卡设计、数值平衡、性能优化这些都需要人的判断。模型能帮你写代码但写代码只是游戏开发的一小部分。但中期看AI会深刻改变游戏开发的工作流。最直接的变化是原型速度。以前做一个游戏原型从想法到可玩可能要几天。现在用模型辅助几个小时就能跑起来。这意味着你可以快速试错试十个想法留下最好的那个。这种迭代速度的提升比省几个程序员有价值得多。对个人开发者来说这是个好消息。以前一个人做3D游戏光是搭框架就要花掉大半精力真正做玩法的時間很少。现在框架可以交给模型你专注于玩法和体验。这降低了独立游戏的门槛会让更多有意思的小游戏出现。对团队来说AI是加速器而不是替代品。它加速的是执行不是决策。团队的核心竞争力还是做什么和为什么做而不是怎么做。模型能帮你更快地怎么做但做什么还得人来定。回到这次实测的三个模型。Step 5 Preview、DeepSeek V4 Pro、GLM5.3它们各有特点但差距没有想象中大。在3D游戏这种复杂任务上它们都处于能用但不好用的阶段。选哪个更多取决于你的具体需求和习惯而不是绝对的强弱。我的建议是都试试找到跟你配合最顺手的那个。然后把它当高级助手而不是独立开发者。你负责思考和决策它负责执行和填充。这个分工下效率提升是实实在在的。最后分享一个小技巧如果你用模型写3D代码一定要让它分步输出。不要一次性要完整代码而是先要场景搭建跑通了再要角色控制再要相机系统。每一步都验证每一步都修复。这样虽然看起来慢但总时间反而更短因为调试成本大幅降低。一次性生成的代码出了问题你都不知道从哪查起。分步生成问题定位在当步修复起来快得多。