用 Claude Code 做 3D:终端里的智能体能干什么

终端里的编程智能体如何搭建 3D 场景:连接怎么建立、什么样的提示词管用、验证循环为何关键、以及它在哪里失败。

由智能体在 Cuberta 中搭建的整片街区俯瞰图:楼群与道路

Claude Code 是为代码库设计的终端智能体:读文件、做计划、改代码、跑测试、读报错,然后再回去改。把同一个智能体通过 MCP 接到一个 3D 编辑器上,会出现一件略微意外的事——它干得不错。不是因为它懂建筑,而是因为搭建一片场景和一次大型重构的形状是一样的:几百次细小的工具调用,每一次都可核查,绝大多数都很枯燥。

编程智能体本来就会做的事

编程智能体真正有用的部分不是它熟悉 JavaScript,而是那个循环:收集状态、选定动作、调用工具、读取结果、发现偏差、修正。Anthropic 对 Claude Code 的描述正是如此:模型行动、观察、决策、重复,有时连续几百轮。剩下的只是工具定义。

一片场景就是一个长的工具驱动任务

看一个人做村庄的白模,你会看到同一个循环。画一条路。站上去。发现太宽。改窄。沿路切出地块。放一栋房子。检查朝向对不对。重复三十次。

三十栋建筑的村庄意味着几百次工具调用,其中几乎没有一次是有趣的。这恰好是编程智能体格外擅长的任务形态:长、有结构、可验证、无聊。它不会在第十九栋房子上失去耐心,也不会在第二十四栋开始偷偷四舍五入坐标。变的只有工具名字,别的都没变:从「读这个文件」变成「列出这个区域里有什么」,从「跑测试」变成「给我你刚放下的那批东西的包围盒」。

迁移不过来的部分

  • 品味。它不会告诉你这个广场是死的、屋顶线太单调、整个村子读起来像一排房子而不是有人生活的地方。这些判断只要你说出来,它立刻接受并执行,但它永远不会主动提出。
  • 缺少反馈时的空间直觉。只凭坐标去推理一块 40 米乘 60 米的地,等于航位推算。算术是可靠的,但「这个间距读起来像不像一条街」不是数字能回答的问题。它越久不把场景读回来,偏移积累得越多。
  • 任何它观察不到的东西。陷进屋顶的烟囱、树冠里的路灯、两面共面的墙在抢同一批像素——如果没有工具报告,对智能体来说就不存在。所有工具测不到的东西由你来充当传感器,这才是把视口一直摆在眼前的真正理由。
  • 判断自己做完了没有。自主循环最常见的失败是过早自信:做出这个东西的智能体天然倾向于接受它。它会报告村子已经完成,而两条路还悬在半空。

把 Claude Code 接到编辑器上

连接是最不值得展开的部分,本来也该如此。Cuberta 在编辑器内部提供一个 Model Context Protocol 服务器。你在应用里按下 Copy connect command,把命令粘进终端,智能体就拿到了编辑器的工具。在 Claude Code 会话里,/mcp 会列出它能看到的服务器及其状态;编辑器在列表里并且已连接,配置就结束了。

Claude Code 是常见的起点,是因为它就在终端里,而不是因为它是必须的——任何 MCP 客户端都能驱动同一批工具。协议层面的讨论另有专文:面向 3D 与游戏开发的 MCP 服务器。下面默认连接已经通了。

第一条提示词

第一条提示词决定了后面所有东西的形状,而它失败的两种方式并不是人们预期的那两种。一种是太笼统。另一种是太有氛围,而且常见得多。

浪费十分钟的提示词

搭一个漂亮的废弃渔村。要非常有氛围,带点阴森感。做得细致、真实一点,多加些有意思的细节,慢慢来,我希望它看起来惊艳。

每一句都是情绪,没有一句可核查。智能体会搭出点什么,因为它总会搭出点什么;等你不满意的时候,你找不到可以指着的那句话。「细致」给了它放四百个物件的许可。「慢慢来」取消了停止条件。「氛围」它看不见,于是用雾和枯树来近似——那是这个词在统计意义上的含义,不是你的意思。

让你有东西可改的提示词

一个约 30 栋建筑的渔村,地形平坦。分批次进行,每批之间停下来。第 1 批:一条沿海岸线延伸约 400 米的路,两条向内陆分出的短路,各以尽端结束。第 2 批:沿这些路切出地块,任何地块都不得越过海岸线。第 3 批:单层木结构住宅,面宽 6 到 8 米,坡屋顶,每栋都朝向自己地块所在的那条路。第 4 批:南端一座石砌码头,带三个栈桥,然后是围栏和小船。第 5 批:傍晚的光,太阳从西侧低角度照射。不要在我标出的区域内施工。每批结束后,告诉我你创建了什么、多少个、包围盒是多少。

它更长,但长度不是重点。数量、尺寸、道路拓扑、执行顺序、一处禁区、一次回读、一条停止规则——每一句要么是数字,要么是关于流程的指令。出问题时你能点名是哪一句被忽略了,那是两行的修正,而不是重写。背后的原理——场景吃结构,单个物件才吃形容词——在文本生成 3D 场景那篇里讲得更透。

验证循环才是关键

一个开完枪就不管的智能体,把整份计划作为一串工具调用一次打出去,从不回头看结果。这很快,也正是很多人得出「AI 搭不了关卡」结论的原因。问题不在于某一次调用错了,而在于误差会沿着链条累积:如果那条海岸路比计划长了 40 米,从它切出的每块地都偏了,地块上的每栋房子都偏了,南端的码头最后落进了水里。

每做完一个动作就把场景读回来的智能体,会在路这一步就抓住它,在任何东西继承这个错误之前。这和在每次改动之间跑测试、而不是攒到最后再跑,是同一种纪律,代价也一样:多几个来回、多花些 token、整体更慢。值得的理由也一样。

做法就是明确要求。把回读写进提示词,它就成了这次会话的习惯。更好的做法是写进 CLAUDE.md——Claude Code 每次会话开始都会加载的项目文件,和那些你已经说腻了的约定放在一起:层高、路宽、材质色板,以及「上一批没确认之前不开始下一批」这条规则。

分批次推进

不要直接要一个村子。先要路网,看一眼,再要地块。这个顺序不是风格问题。每一批都是下一批的输入,所以越靠前的批次,出错的代价越大。

批次决定什么进入下一批前检查
道路后面每一批都要继承的骨架路口真的接上了;总长度和计划一致
地块哪里能建、哪里不能没有地块骑在路上,也没有超出场地
建筑体量、轮廓、面宽统一的层高约定;每个立面都朝向自己的路
陈设人行道、路灯、树、围栏、招牌没有互相穿插,没有悬空,间距均匀
光照时间、太阳角度、天空阴影方向一致;重要的东西没有留在暗处

分批还解决了上下文问题。一次长时间的搭建会用工具返回结果塞满模型的上下文窗口——你要求的每一次回读,都是它现在必须扛着的文本。/context 显示窗口被什么占着,/compact 把对话压缩以腾出空间。批次之间是做这两件事最安全的时机,因为场景活在编辑器里,而不在对话里。对话是可以丢弃的那一半。

出问题的时候

与其争论,不如把地划出来

当智能体一次次把房子放在本该是广场的位置,解法不是第三次换措辞。在 Cuberta 里,你可以在开口之前就标出哪里能建、哪里不能,而禁建区是约束,不是请求。花三十秒拖一条边界,好过三轮「不对,不是那里」。

撤销一步,而不是推倒重来

一批做砸之后的本能是清空场景、换个更好的提示词重来。那等于为了修第五批而丢掉四批正确的成果,而新的一轮只会犯不同的错,不会犯更少的错。撤销最后一步,用一句话说清哪里不对——「房子朝着水,应该朝向自己地块所在的那条路」——然后只让它重做那一批。上下文用尽时重启对话,几乎永远不要重启场景。

当它说自己做完了

要数字,不要总结。多少栋建筑。整体包围盒是多少。有多少栋距离道路中心线超过 5 米。有没有物件掉到地面以下。真正检查过的智能体,几次工具调用就能从场景里答出来。在猜的智能体会给你一段自信但没有一个数字的话,那就是破绽。

成本、时间,以及它替代不了什么

时间是分钟级,不是秒级,也不是手工白模要花掉的一个下午。这几分钟应该用来掌舵,而不是走开——上面整篇的论证就是:正是监督让产出变得可用。

真正的成本是 token。每次工具调用来回都要花 token,而本文刚用一整节辩护过的验证正是贵的那一半,因为回读只有在结果重新进入模型上下文时才有意义。编辑器的工具定义在你打第一个字之前就已经占掉了窗口的一部分。这些都不隐蔽:Cuberta 本身免费,自带的模型和材质离线可用,但模型访问权限要你自己带,所以 token 账单是你的,窗口填到什么程度用 /context 就能看到。

最后一条是诚实的局限:它替代不了关卡设计师,它替代的是设计师最开始的那两天——白模、三百次没人愿意手工做的摆放、沿街两侧每 25 米放一盏灯的那一遍。替代不了的是关于这个地方为什么存在的判断:视线该落在哪里、哪条街应该比实际需要的更窄、什么东西本就不该出现在这里。有设计师又有智能体,一小时就能拿到值得被批评的版本,而不是一周。没有设计师,你得到的是一个技术上正确、却无话可说的村子。

这大概就是这次迁移的公道总结。Claude Code 带来了耐心、愿意做四百个微小而正确的决定,以及检查自己工作的习惯。它没有带来观点。那部分依然是你的活。