用 AI 智能体搭建 3D 村庄:分五轮做完
从空场景到可以走进去的村庄,分五轮完成:地形、道路、地块、建筑、陈设——每一轮都给出可以直接照抄的指令。
做村庄的第一次尝试通常是一句指令:「建一个有 30 栋房子的中世纪村庄。」返回来的是三十栋房子摆在平地上,高度差不多,还有一条到最后一栋就断掉的路。几何体本身没有错,它只是不像一个地方。
解法不是把指令写得更长,而是每条指令少说几件事,并按真实聚落形成的顺序来说:地面、道路、地块、房子、陈设、光。五轮,加一次检查。第一轮的错误代价是一分钟;同样的错误到第四轮之后才发现,代价是整个村庄。
下面的做法假设有一个 AI 智能体在驱动真正的 3D 编辑器:它在每一步之间把场景读回来,你也可以随时打断它——「分轮」正是靠这一点才成立。Cuberta 就是这样一个编辑器:场景层级的工具通过 Model Context Protocol 开放,按下 Copy connect command,把命令粘进终端,智能体就连上了。下面的指令就是我实际会敲进去的样子。
动手之前先把需求定下来
村庄的质量大半在连上智能体之前就决定了。判断一个问题该不该进需求的标准很简单:答案会不会改变几何体。「温馨」不会,「四十六栋建筑」会。把答案写下来留着——把话固定下来,日后才能指着「被忽略的那一句」。
会改变几何体的五个回答
- 多少栋建筑。要一个数字,不要形容尺寸的词。二十五栋读起来是小聚落,六十到八十栋是有中心的村庄,超过一百五十栋就是小镇了。独栋住宅按 400–500 m² 的地块算,大约每公顷 20–25 户,所以五十来栋需要三公顷左右的建成用地——大致 250 × 250 m,外面再留田地。
- 年代与地域。它们决定材质色板和屋顶坡度,这两样是几何,不是装饰。
- 地形。平地、山谷、坡地、海岸——五个里最吃重的一个。坡地带来挡土墙、层层跌落的地块和回头弯;河滩一样都没有。
- 用途。在视高走进去,以 40 km/h 开车经过,还是用 RTS 视角俯视。这决定细节放在哪里,也决定不放在哪里。
- 边界在哪里收。田地、树林、水面,或一条驶出画面的路——否则聚落会渐渐淡进一片没做完的地面。
第一轮 —— 地面与道路主干
先地形再道路,因为之后的一切都要引用它们。道路是主干:建筑挂在它上面,陈设沿着它铺开,玩家走的也是它。这里出的错,后面每一轮都会继承。
空场景。做一块 400 × 400 m 的地面,形成一个浅浅的河谷:北缘一道山脊,比中央高出 18 m,中间是平地,一条溪流自西向东穿过低处。然后一条主路,宽 6 m,两侧各 1.8 m 人行道,从西侧进入,沿溪流北岸缓缓弯曲,从东缘离开。主路上分出两条支巷,宽 4 m,无人行道,各长约 80 m,尽端设回车场。主路跨溪处架一座石桥。其他先都不要——不要建筑,不要道具,不要树。
其中两个数字是实打实起作用的。6 m 是两条 3 m 车道,也就是两车对向通过的真实宽度:NACTO 建议城市行车道 3.05 m,而 3.0 m 是居住区支路常见的下限。1.8 m 的人行道刚好够两个人错身。定好之后,沿路从这头走到那头,中途不许离开路面;走不通,第一轮就没做完。
第二轮 —— 划分地块,以及哪里不许建
这一轮最容易被跳过,而它恰恰把一堆散件变成村庄。建筑坐落在地块上,地块以一致的退距面向道路,仅这一条关系就构成了「街道之所以像街道」的大部分。
先什么都别建。沿道路把土地划成地块。穿过中心的那 200 m 主路两侧:面宽 15 m、进深 30 m,每块自人行道后退 4 m。两条支巷沿线:地块大一些,25 × 40 m。把下面这些标成禁建区——溪流本身以及两侧各 8 m,12 m 等高线以上的山脊,两个回车场,还有桥南岸一块 30 × 40 m 的矩形,那是广场,保持空着。在往里填任何东西之前,先把地块轮廓给我看。
关于禁建区的那句话,是整套流程里杠杆最大的一条指令。智能体会填满空间。你不说,房子就会出现在溪岸上、山脊上,以及你本打算留作草地的正中央。把每一块空地按功能命名,也能防止它在三轮之后被「好心」填上。在 Cuberta 里,这些区域可以直接在视口中标出来,不必用文字描述。
第三轮 —— 建筑
地块划好、禁建区标好之后,这一轮就是算术:数量、一套层高约定、一个尺寸区间,以及一个封闭的色板。
现在建房子,一共 46 栋。中心地块上:30 栋两层住宅,占地在 7 × 9 m 到 9 × 12 m 之间,层高 2.8 m,门高 2.0 m,双坡屋顶坡度约 40°,全部面向道路。两条支巷上:12 栋更大的独栋住宅,一层半,不超过 12 × 14 m。广场四周:4 栋三层建筑——一家客栈、一间铺子、一间带宽车门的作坊,以及一座小教堂,钟塔可以到 16 m。材质只用五种:白灰墙、灰石、深色木材、红黏土瓦、板岩。所有墙面非灰即石,所有屋顶非瓦即板岩。在这个色板内变化开间、进深、屋脊朝向和颜色。不要变层高、门高和退距。
变化必须有边界
不加约束的智能体,典型问题不是重复,而是把「做得有变化」当成许可,于是 3 m 高的门紧挨着 1.6 m 的门。真实的乡土建筑在很窄的区间里变化,因为大家用的是同样长度的木料、同样的砖,以及同一个适应当地降雨的屋顶坡度。明确说出哪些尺寸可以动、哪些冻结,换来的才是一条街,而不是一页材质样品。
这一轮不做的事
室内。四十六栋带家具的房子是另一个量级的工作,而且几乎全花在没人会进的建筑上。现在只做外壳,之后再给真正会进去的那两三栋布置内部——那是另一套流程。
第四轮 —— 陈设,以及「有人住」的 80/20
「这里有人住」的感觉,大部分来自三样东西:标出每块地边界的东西、说明这地方入夜后仍在使用的东西,以及按人的逻辑而不是噪声函数种下的植物。其余多半是杂物。
陈设轮。每一段面向道路的地块边界都做围栏或矮石墙,高 1.2 m,材质与其后房屋的墙面一致。路灯只装在主路上,灯杆 5 m,每 30 m 一盏,两侧交错。树:广场南侧一排六棵,中心地块的后半部种果树,禁建等高线以上的山脊做茂密的混交林,溪边种芦苇。大约三分之一的地块上,各加一样:柴垛、雨水桶、板车、长凳、晾衣绳。路面上不放任何东西,广场上除了那几棵树和两条长凳也什么都不放。
居住区 5 到 6 m 的灯杆,通常按三到五倍安装高度布置,也就是 18–30 m;5 m 灯杆用 30 m 间距,对一个只照亮主街的村庄来说恰到好处。也请注意那条上限:大约三分之一的地块。没有它,每一块地都会有一垛柴,而规律出现的杂物比空着更难看。
第五轮 —— 光照与时间
把时间设在初秋日落前一小时左右:太阳低垂在西北偏西方向,高度角约 12°,色温偏暖。晴天,带一些高云。把路灯以低强度点亮,让它们看得出来但不与阳光相争。检查山脊是否在东侧地块上投下阴影。
太阳角度与其说是照明决策,不如说是构图决策。低角度的阳光斜掠过立面,把相邻屋顶的坡度区分开,也让第一轮做的地形重新变得可读;正午的太阳则把这一切压平。进引擎之后光照总归会重做,但现在还是要设:检查轮里的一切判断,都是在这套光下做出的。
会出什么问题,以及该怎么说
三类问题几乎覆盖了全部。它建得太多:你要 46 栋,它给了 71 栋,把每个空隙都填满——与其说不听话,不如说是默认行为,范围一旦含糊,智能体就会扩张。它自我重复:同一栋房子镜像十一次,沿街一侧排开。尺度会漂:通常发生在两轮的交界处,于是教堂是对的,房子却悄悄缩了水。
| 你看到的 | 该怎么说 |
|---|---|
| 建筑比要求的多 | 删掉第二轮划定的地块之外的一切。四十六是硬上限,不是目标值。 |
| 同一栋房子出现十一次 | 色板保留,把主路北侧的占地尺寸重新生成一遍。相邻两栋不得同时在开间和屋脊朝向上相同。 |
| 第三轮之后整体变大了 | 用 1.8 m 的参照方块逐栋量一扇门,凡是不在 1.9–2.1 m 之间的重建。 |
| 物件悬空或陷进地里 | 把所有物件重新落到地形表面:相对其下方地面的高差不得超过 2 cm。 |
| 道路在最后一栋房子处断掉 | 把主路两端延伸到地面边界。 |
两个习惯能挡掉大半。某一轮出问题时,撤销这一轮,而不是打补丁:给失败的第三轮打十五个补丁,比在指令里多写两句话重做一遍更费时间,而且会留下一堆孤儿物件。以及,在每一轮开头复述那些冻结的约束——色板、层高、禁建区。
导出之前的检查轮
这里花几分钟,抓的全是导入之后修起来很贵的问题。
- 站到一个 1.8 m 的方块旁边。把它放在村口,沿主街望过去。标准门高 2.03 m,所以门应当比方块高出大约一掌。
- 抽查门与层高。在村里散开取八栋建筑,每栋量一扇门。不在 1.9–2.1 m 之间就是错的,层高不在 2.6–3.0 m 之间同样是错的。
- 把每条路都走一遍。主路从这头走到那头,每条支巷走回路口,人行道要连续穿过路口并跨过桥。
- 找悬空物。压低视角绕场一圈,太阳在你背后;悬空物靠「缺失的接触阴影」最容易发现,而不是靠坐标。
- 数材质。第三轮说的是五种,场景却报三十四种,那就现在合并,不要等到导入之后。
- 走到边界上。玩家能到达的每个地方,要么合理地延续下去,要么被挡住。
然后导出。带纹理的 GLB 或 FBX 覆盖 Unity、Unreal、Blender 和 Godot。有一条单位约定值得先记住:glTF 用米,FBX 默认用厘米,Unity 把一个单位当作一米,Unreal 当作一厘米,所以按缩放 1 导入的 FBX 有时会差一百倍。从第一轮就用真实的米来搭建,能把这件事降级成一个复选框。
导出前按功能命名——道路、建筑、道具、植被——好让接手的人有东西可选。再往后是另一摊活:合并材质、实例化与 LOD,以及决定场景在引擎里落地效果的导入设置。
五轮下来,真正敲进去的文字大约十句话。其余时间都在看——而这本来就是这份工作本身。分轮不是某个工具的特性,它是让智能体不必把整座村庄装进一个念头里的办法。