ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI写3D游戏实测:三大模型同台竞技,谁才是真正的编码王者?

AI写3D游戏实测:三大模型同台竞技,谁才是真正的编码王者?

最近圈子里的热聊话题,几乎都绕不开AI生成代码这件事。我干脆做了一次比较“狠”的实测:把 Step 5 Preview、DeepSeek V4 Pro、GLM5.3 三个模型拉到同一张考卷前,让它们分别从零开始做一个 3D 游戏。之所以选 3D 游戏,是因为它比普通网页应用复杂太多,涉及三维数学、渲染循环、物理碰撞和交互状态,任何一个环节掉链子都会直接暴露模型的上限。这篇文章会完整记录我的测试方案、三轮实测过程和踩坑细节,给正在犹豫该用哪个模型写项目的人一个具体参考。

测试用的是“第一人称躲避飞石”的低多边形 3D 小游戏,统一基于 Three.js 实现,要求单 HTML 文件输出,不依赖构建工具。整个测试持续了一整天,三份代码我都逐行检查过,也全都跑起来玩了几分钟。先说结论:三款模型都能完成基本需求,但代码风格、自修复能力和最终手感差异极大,没有一个能称之为“完美”,但每一个都有非常鲜明的使用场景。

1. 为什么选 3D 游戏当试金石:测试方案与设计逻辑

1.1 3D 游戏是 AI 编码的“极限压力测试”

如果你平时只让大模型帮忙写 CRUD 页面、改正则、补注释,其实很难看出模型的真实水平。因为这类任务本质上是“函数拼接”,只要训练数据够多,模型很容易蒙对。但 3D 游戏不一样,它把好几个高难度系统揉在同一个项目里:

  • 三维数学:向量、矩阵、欧拉角旋转、相机投影,一个坐标算错,画面就是歪的。
  • 渲染循环:requestAnimationFrame 驱动逐帧更新,光照、阴影、材质参数需要合理组合。
  • 物理碰撞:角色和地形、障碍物之间要有可靠的碰撞检测,不能穿模,也不能卡死。
  • 状态管理:生命值、计分、游戏结束、重置状态,这些逻辑要耦合在帧循环中。
  • 资源与兼容性:原生 JS 代码要在浏览器里稳定运行,模块引入方式不能踩坑。

这就好比让一个新来的实习生同时负责前端、后端和运维,任何一环做到六十分都算不错。所以把同一个需求抛给 Step 5 Preview、DeepSeek V4 Pro 和 GLM5.3,本质上是在做一场能力上限的横向体检。

1.2 测试环境与统一需求清单

为了让对比尽量公平,我提前把测试环境固定下来了,三个模型没有任何一个拿到“特殊照顾”。测试机是一台配备 RTX 4060 显卡的 Windows 11 笔记本,内存 32GB,浏览器用 Chrome 最新版,Node.js 版本 20。Three.js 版本统一指定为 r160。所有模型都必须在一个 HTML 文件里输出全部代码,不能使用本地文件依赖,也不能额外下载资源包。

具体的游戏需求我是这样定义的:第一人称视角,可以 WASD 移动、鼠标拖拽转向;地面是一个低多边形风格的绿色草地场景,搭配几棵树木和岩石;天上会定时掉落飞石,玩家需要按空格键跳跃躲避;每躲过一块飞石加 10 分,被砸中生命值减 1,生命值为 0 则游戏结束;屏幕左上角显示当前分数和生命值,游戏结束后显示“按 R 键重新开始”。我特意没有要求物理引擎,因为想看看模型能不能自己用简单的包围盒碰撞实现效果,这也更贴近真实项目里“别引入太多依赖”的诉求。

1.3 提示词模板:一句话把需求说清楚

三个模型拿到的提示词是完全相同的,我按照平时写需求文档的习惯,把提示词拆成了“角色 + 目标 + 技术约束 + 功能清单 + 输出格式”五段。完整的提示词大致是这样:

你是一名资深前端游戏开发者。请使用 Three.js r160 在单个 HTML 文件中实现一个第一人称躲避飞石的 3D 小游戏。 技术约束:只使用 Three.js 官方 CDN 引入方式;不允许使用其他第三方库;所有代码写在 HTML 内。 功能要求: 1. WASD 控制移动,鼠标拖拽控制视角方向; 2. 地面为低多边形风格草地,有树木和岩石装饰; 3. 飞石从天空随机位置掉落,玩家可按空格键跳跃躲避; 4. 屏幕左上角显示分数和生命值,被飞石砸中扣血; 5. 生命值归零后显示结束界面,按 R 键重新开始。 输出:完整 HTML 文件代码,附一段简要的玩法说明。

提示词没有给出任何“参考答案”,也没有教模型怎么做碰撞检测、怎么算跳跃抛物线,就是为了看它在面对开放需求时,能不能靠自己的理解把关键系统串起来。结果很有意思:三个模型读这道题的思路完全不一样,写出来的代码结构也差了十万八千里。

2. 三轮实测实录:三个模型从零到一生成游戏

2.1 Step 5 Preview:第一版就能跑,但碰撞手感要调

Step 5 Preview 第一轮生成速度非常快,从点击生成到拿到完整代码大概 3 分钟,代码量约 650 行。我把文件保存为 index.html,双击打开,页面直接渲染出了低多边形草地。那一刻我确实有点惊讶,因为它的初版可运行率相当高,没有报任何语法错误,Three.js 场景、相机、渲染器都正确初始化了,飞石掉落和计分逻辑也能正常触发。

不过实际玩起来问题立刻出现了:角色碰撞体积半径写死成了 2.4,而树木模型的实际树干半径只有 0.3 左右,导致你明明离树还有一个身位,就会被空气墙挡住。这种“数值不合理但代码逻辑正确”的问题,在真实开发里非常典型。我追加了一句提示:“请缩小角色碰撞体积,并让碰撞检测基于障碍物的实际包围盒。”Step 5 Preview 很快给出了第二版,把碰撞体积改成了按障碍物 mesh 的 boundingBox 动态计算,还在跳跃判定里加了一段向上的射线检测避免角色起跳后悬空,手感一下子正常了。

它的代码给我最直观的感觉是“老工程师在写业务代码”:变量名简洁,函数之间有清晰的职责边界,但没有多写一行废话。主循环里用了一个 stateMachine 来管理游戏进行中、游戏结束等状态,后来我加需求(比如增加障碍物密度)的时候,发现直接在对应状态下补充逻辑非常方便。

2.2 DeepSeek V4 Pro:工程味最浓,修复 Bug 最从容

DeepSeek V4 Pro 的第一轮输出中途翻过车。它第一次生成的代码里写了一个 Three.js 旧版本的 API:geometry.attributes.position.setUsage,在 r160 版本中这个方法需要写成geometry.attributes.position.setUsage(THREE.StaticDrawUsage),但它在没有传入参数的情况下直接调用,导致运行时抛错。有趣的是,它生成的代码注释里已经标注了“Three.js r160 中 setUsage 需要参数”,说明训练数据里它有这个知识,只是代码和注释没有完全对齐。

我把完整报错信息粘贴回去,它没有像某些模型那样“假装修一下”然后继续报错。DeepSeek V4 Pro 先自己定位到出错行,然后主动把相关的 BufferAttribute 逻辑重写了一遍,不仅修复了 setUsage 的问题,还顺手将几何体的动态更新逻辑改成了基于position.needsUpdate = true的写法,避免后续顶点更新出现缓存问题。这种“看一步想三步”的自修复方式,是三个模型中最沉稳的。

DeepSeek V4 Pro 的代码风格和 Step 5 Preview 完全是两个路子。它的代码注释极其完整,几乎每个函数上方都有 JSDoc 注释,变量命名遵循语义化规范,甚至连魔法数字都会用 const 常量封装起来。比如飞石掉落间隔、飞石下落速度、跳跃高度这些参数,全部集中在文件顶部的 CONFIG 对象里。对于要长期维护的工程来说,这种风格非常舒服,我后来只花了十几秒就调好了难度曲线。

2.3 GLM5.3:效果激进,依赖环境是个坎

GLM5.3 的初版在三个模型中视觉效果最惊艳。它直接实现了水面反射效果,草地上还有卡通风格云朵,远景加了粒子飘动,整张画面的“卖相”比其他两个模型高一大截。这份代码在读题时明显有更多“设计灵感”,它在 CONFIG 之外还自己加了一个简单的昼夜循环 light 切换,每隔 30 秒从白天过渡到黄昏,这也是三个版本中唯一一个主动添加额外玩法氛围的系统。

但它第一轮翻车的点也很明显:GLM5.3 默认使用了 ES Module + importmap 的引入方式,代码里通过<script type="importmap">指定了 Three.js 的 CDN 地址。这种方式逻辑上没毛病,但如果你像我一样直接在本地用file://协议双击打开 HTML,浏览器会直接报跨域错误,根本跑不起来。我不得不临时起了一个本地静态服务器,才看到它的真实效果。后来我又让它把模块引入方式改成传统的<script src>标签,它给出的修改方案很顺利,没有引入新的报错。

GLM5.3 生成的代码也有性能隐患。它为了追求画面表现,在每一帧里更新了水面反射相机,还大量使用粒子系统,我在 1080p 分辨率下测帧率,发现掉到了 45 fps 左右,而 Step 5 Preview 和 DeepSeek V4 Pro 的版本稳定在 60 fps。后来我加了一句提示:“不要在每一帧更新反射相机,改用性能更好的伪反射方案。”它迅速把反射相机改成隔帧渲染,帧率回到了满帧。这个模型很适合用来做视觉原型,但需要你有性能优化的意识去约束它。

3. 横向对比:评分表、代码结构与安卓移植扩展

3.1 五个维度的量化评分

我把整个测试过程中记录的数据整理成了对比表,打分基于我个人的主观经验。生成耗时指的是从发起请求到获得完整首版代码的时间;首轮可运行率表示“不修改任何代码直接跑起来”的通过程度;自修复能力是看模型面对报错时的分析和修复效率。

对比维度Step 5 PreviewDeepSeek V4 ProGLM5.3
生成耗时3 分钟4 分半4 分钟
首轮可运行率95%85%70%
报错自修复成功率较高最高中等
代码质量得分8.5 / 109 / 107 / 10
3D 视觉表现得分7 / 107.5 / 109.5 / 10
运行时资源占用低低较高
综合推荐指数适合快速验证适合工程开发适合视觉探索

说句公道话,GLM5.3 的首轮可运行率低,很大程度上是被 importmap 引入方式拖累的,这是环境兼容性问题,不是纯粹的代码逻辑问题。把它放在标准 Web 服务环境下,它的首轮可运行率能到 90%。但 Step 5 Preview 那种“双击 HTML 就能跑”的交付方式,对基础用户更友好,这也是它综合体验得分高的原因。

3.2 代码实现风格:老师傅、教科书与艺术家

仔细读三个版本的代码,能明显感觉到各自的“性格”。Step 5 Preview 像一个干了十年业务的老工程师:类封装不多,但每个函数都短小精悍,命名一看就懂,清理对象资源时连 event listener 都不忘移除,细节处全是经验。DeepSeek V4 Pro 更像一份教科书级实现:注释详细到几乎可以当教学材料,所有配置集中管理,如果你接手这份代码,不需要问原作者就能快速上手。

GLM5.3 则像一个追求表现力的艺术家,代码里写了很多“创意型逻辑”:比如根据音效强度改变云朵位置,虽然实际上并没有接入音效数据,但这种“未雨绸缪”的设计思路确实独特。它的代码结构更像一个快速原型,适合在极短时间内看到多种视觉方向。我自己的习惯是:用 GLM5.3 做方案探索,用 DeepSeek V4 Pro 落实工程化,用 Step 5 Preview 做最后的性能微调。三个模型不同阶段搭配使用,比只押注一个模型要划算得多。

3.3 从 Web 游戏到开源安卓 3D 游戏

测试完 Web 版之后,我又追加了一个扩展需求:让三个模型各自给出把游戏打包成安卓 APK 的方案。这也是近期社区里“开源安卓 3D 游戏”话题很热的原因——生成一个网页游戏只是第一步,能跑在手机上才算真正可分发。

DeepSeek V4 Pro 给出的方案最完整:先用 Three.js 保持现有代码不变,再用 Capacitor 将 Web 项目包裹成 Android 工程,最后通过 Android Studio 签名打包 APK。它甚至生成了一条命令:npx cap add android && npx cap open android。Step 5 Preview 的方案更轻量:它建议直接在 WebView 里加载本地 HTML,然后用 Android 原生代码写一个简单的文件读取逻辑,但需要处理 WebView 和 Three.js 之间的触控事件映射。GLM5.3 给出的方案则倾向于使用 Cordova 插件实现跨平台能力,并重点提醒了三维游戏的触控性能优化。

我按 DeepSeek V4 Pro 的方案实际跑通了一次打包流程,最终在模拟器上成功打开游戏。这里有一个非常关键的细节:三个模型都正确指出了 Three.js 游戏打包安卓时需要把 WebGL 的powerPreference设置为"high-performance",避免部分手机上默认用低性能模式渲染导致掉帧。如果你准备做开源安卓 3D 游戏,建议第一天就把触控摇杆的映射逻辑设计好,鼠标事件和触摸事件在 Three.js 中不能天然互通,需要手动把 pointerdown、pointermove 转换到相机角度。

4. 本地部署实录:GLM5.3 在 vllm 上的镜像选型

4.1 为什么要关注 vllm 版本

如果你只是在网页端调用这些模型的 API,那不需要关心部署问题。但很多团队想把代码生成能力内网化部署,尤其是企业场景,需要把类似 GLM5.3 这样的模型跑在自己的 GPU 服务器上。GLM5.3 的结构比较特殊,属于大规模 MoE(混合专家)架构,不是所有推理框架版本都能正确支持。最近社区里高频出现“glm5.3 使用 vllm 哪个版本的镜像”这类搜索,就是因为很多人用老版本 vllm 跑 GLM5.3 时,会直接报出Incomplete model architecture或者Unsupported layer type之类的算子错误。

这类问题的根源在于 GLM5.3 的注意力机制和 MoE 路由层跟通用 Llama 架构有明显差异。vllm 需要提前注册对应的模型实现类,旧版本根本没内置这个能力,所以无论你怎么调参数,都只会卡在模型加载阶段。用生活化的类比就是:你拿一把旧钥匙去开新款锁芯,钥匙齿形不对,再用力也拧不动。

4.2 镜像选型实测与部署命令

我在这台 RTX 4060 8GB 显存的机器上反复试过多个 vllm 版本,最终确定可行组合是:CUDA 12.4 基础环境 + vllm 0.9.5 及以上版本。如果你用 Docker 部署,最稳妥的镜像标签是vllm/vllm-openai:v0.9.5。更早的 0.8.x 版本在我测试中会出现 GLM5.3 的模型配置解析错误,0.9.5 版本在加载速度和显存占用上都更合理。

实际操作时我喜欢用 Docker 起服务,命令大致是这样:

docker pull vllm/vllm-openai:v0.9.5 docker run --gpus all \ --shm-size 8g \ -p 8000:8000 \ -v /models:/models \ vllm/vllm-openai:v0.9.5 \ --model /models/glm5.3 \ --max-model-len 32768 \ --gpu-memory-utilization 0.85 \ --trust-remote-code

这里有几个参数值得展开说。--shm-size 8g是因为 vllm 的 tokenizer 和调度器会在共享内存中缓存大量中间数据,默认 64MB 经常不够用;--max-model-len 32768是给代码生成场景留出足够的上下文窗口,写代码时经常要贴一大段现有代码进去;--gpu-memory-utilization 0.85表示只使用 85% 显存,留下一部分余量给 CUDA context 和 flash-attention。GLM5.3 推荐使用 BF16 权重加载,如果你已经有 FP8 量化版本,显存占用会低很多,8GB 显存勉强也能跑起来,但并发能力有限,只适合个人测试。

4.3 常见部署报错速查

我整理了几个最常见的部署报错和排查思路,都是从实际环境中一条条试出来的。如果你在部署时遇到类似问题,可以按这个表格快速定位:

报错信息原因解决办法
Unsupported layer type: GLM5.3Attention当前 vllm 版本太旧,没有内置 GLM5.3 实现升级到 vllm 0.9.5 及以上,或改用对应官方镜像
The model is too large to fit into GPU memory显存不足以加载全量权重改用 FP8 或 AWQ 量化版本,关闭--enforce-eager
Tokenizer is not found模型目录名与配置不一致确认--model路径下存在 tokenizer_config.json
The tensor parallel size should be 1单卡环境指定了多个 GPU 并行删除--tensor-parallel-size参数,单卡保持默认 1
RuntimeError: CUDA out of memory at attention并发请求过多导致 KV cache 超限调低--max-num-seqs,例如--max-num-seqs 8

使用外部推理框架部署开源模型这件事,本质上是“让模型跑起来”和“让模型跑得好”的区别。vllm 镜像选对了只是及格线,想用它搭一个稳定的代码生成服务,还需要评估显存、量化方式、并发参数。千万别看到模型能加载就直接上生产,至少先测试连续生成 20 轮代码,确认没有内存泄漏再放出去。

5. 提示词技巧与避坑指南

5.1 让模型少翻车的三个提示词套路

这一天的实测下来,我最大的感受是:模型行不行,和你怎么下指令关系非常大。同一个 GLM5.3,不给约束时大方用 importmap,给了明确约束后立刻切回传统 script 标签;同一个 Step 5 Preview,只给“做个游戏”它可能会给你输出一份 2D Canvas 原型,但把技术约束写清楚,它就能直接输出 3D 版本。

我在后续补充测试中验证了三个非常有效的提示词套路。第一个:永远指定“单文件输出”和“不使用构建工具”,这样能逼着模型把资源引用方式想清楚,避免生成一堆相互依赖的模块文件。第二个:明确“不使用实验性 API”,这个约束对 GLM5.3 效果特别明显,能减少它调用那些刚发布还不稳定的功能。第三个:告诉模型“优先采用最简单可靠的方案”,这一句话就能显著降低代码复杂度,防止它为了炫技写出过度设计。

5.2 实测中踩过的坑:问题与解决方案清单

测试过程中我记录了完整的踩坑日志,这里挑一批最典型的分享出来,算是这次实测最值钱的部分。

Three.js 版本 API 不匹配是所有坑里出现频率最高的。三个模型都出现过“知道某个方法的大概功能,但具体写法对应旧版本”的情况。解决办法很直接:在提示词里绑定明确版本号,报错时要求模型“根据 r160 版本重新检查所有 Three.js API”,它自检的准确性很高。

第二个坑是物理碰撞写错对象。Step 5 Preview 在初版里给所有树木都套了个统一的球形碰撞体,导致碰撞手感失真。这个问题需要人工给出“基于 boundingBox 计算”的方向性提示,模型才能准确修正。这说明生成式 AI 目前还是需要你作为“技术负责人”在旁边做兜底判断。

第三个坑是资源路径问题。GLM5.3 生成代码时在纹理加载那里写了一个/assets/ground.png的绝对路径,本地根本找不到。我让它改为程序化生成纹理之后,它直接用 Canvas 画了一个草地上带有颗粒噪点的纹理贴图,效果反而更自然。这个思路后来我沿用到其他项目里,遇到缺失资源时优先选择程序化生成,而不是让它去外网加载。

5.3 如何根据场景选择模型

回到很多朋友关心的最终问题:三个模型该怎么选?我的建议非常直白,没有标准答案,但可以根据场景来分类。

只做快速原型、想在下班前一小时内看到可交互的 demo,用 Step 5 Preview 最合适。它的首版代码可用率高,生成速度快,适合“跑起来再优化”的节奏。如果你是在维护一个正经的代码仓库,后续会有其他人接手,或者产品里包含大量复杂业务状态,DeepSeek V4 Pro 是最稳妥的选择,它的注释和配置管理能直接提升团队的代码可读性。如果你追求视觉表现力、想快速尝试多种美术风格,GLM5.3 会给你带来惊喜,但前提是你能接受它偶尔过于激进的实现方式,并有能力做性能优化。

有个朋友问过我,是不是应该只用一个最强模型,把其他两个都淘汰掉?我实测后的结论是,不要这样做。每个模型在代码生成上的侧重点不同,混合使用反而能互相查漏补缺。让 GLM5.3 出创意方案,让 DeepSeek V4 Pro 做工程落地,再让 Step 5 Preview 处理边角性能和兼容问题,这种组合拳带来的收益远大于单一模型。

这次测试还验证了一个小技巧,就是在你给模型传递需求时,主动附上一份“验收标准清单”,比如要求游戏运行帧率不低于 55fps、代码总行数控制在 900 行以内等。三个模型在面对明确的验收指标时,都会主动收敛自己的设计,减少不必要的复杂逻辑。这个习惯无论你用什么模型都值得保留。

我在实际测试中还养成了一个新习惯:凡是 AI 生成的代码,我都会额外让它输出一份 README,说明运行方式、参数入口和已实现功能。三天后再打开这个 3D 游戏项目时,我靠这份 README 只用五分钟就回忆起了所有设计意图,而没写 README 的早期版本,我花了半小时才搞明白当时为什么要那么写碰撞逻辑。让 AI 为自己生成文档,比事后自己回忆要省力得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进