TechNeko
返回笔记列表
LAB NOTE / 2026-10-28

用 AI 做 MMORPG 地编:一张森林地图的五天

一款受《魔剑》(Shadowbane) 启发的 PvP 沙盒 MMORPG,Unreal Engine 5.8 客户端加 C# 权威服务器,代码和关卡全部由 AI 智能体完成。这篇以第一张正式地图“北林”为例,讲用 AI 做地编时碰到的问题和解决办法:四步工作流、一套“改文件再生成”的地图工具包,以及一路上踩到的坑——崖壁太规整、看到的地面和踩到的不一样、地图里冒出两千多个竖井、截图里的火凭空消失。

这是什么

NSB 是我们正在做的一款 PvP 沙盒 MMORPG,精神上继承二十年前的《魔剑》:玩家自己建城、打仗、抢地盘。客户端用 Unreal Engine 5.8(C++),服务器是 C# / .NET 10 写的权威服务器,世界由一块块“碎片”地图拼成。

项目的第一个提交是 2026-10-28 02:37。到 11 月 1 日,一共 117 个提交:文档、数据表、服务器、客户端、地图,全部由 AI 智能体完成。

这篇只讲其中一件事:用 AI 做地编时碰到了什么问题,以及怎么解决的。例子是第一张正式地图“北林”——一片约 5 × 4 千米、长在断崖台地上的原始森林,台地之间是看不见底的雾谷。

北林的概念图(只用文字生成):参天大树、断崖台地和雾谷

一个人,加一支 AI 团队

前几天是一个 AI 智能体(Claude Code)包办所有事。最后一两天,工作量大到一个上下文装不下,我们在 Cindy 里改成了多智能体协作,分工像一个小工作室:

角色由谁担任做什么
主管(Lead)Claude拆任务、派活、验收、汇总,自己不写代码
程序Claude Code写工具、改布局、重建关卡、跑验收
美术总监Codex进编辑器看画面,和原画逐项对比,写审查报告和返工清单
助理另一个模型查资料、读提交记录、整理事实

AI 怎么“进编辑器”?UE 5.8 自带一个 MCP 服务器,智能体通过它查询和摆放关卡里的东西、导入模型、改材质、移动相机截图,不需要人帮忙点鼠标。

工作流:四步,每步停下来给人看

北林最早是凭感觉直接搭的:第一天傍晚就有了一座能联网进去的浮岛,营地、怪物、传送门都在。但试玩马上暴露出一堆问题:栅栏四面漏风、东西穿模、主路长到一口气跑不完。这些本来在“量尺寸”的阶段就该发现。

于是第一天深夜定下了四步流程(项目决策 D062),之后所有地图都照着走:

步骤做什么产出
1 概念图写设定卡,只用文字生成 3~5 张概念图;列出光源,标出每样东西打算用哪个素材设定卡、概念图、提示词记录
2 顶视分区图写布局文件,脚本画出“北在上、100 米一格”的分区图,算出跑一趟要多久、多少耐力,检查怪物仇恨范围会不会碰到主路和门口02_layout.json、分区图
3 比例尺图在编辑器里量每个模型的真实尺寸、原点、碰撞,和矮人、人类、半巨人站成一排截图尺寸表、问题清单、比例尺图
4 生成只读前面的文件,建关卡、撒树、摆设、导导航网格、写服务器的地图数据、截图验收关卡、导航网格、地图数据、对照图

每一步做完先确认,再做下一步。 试玩发现问题,先判断是哪一步的:气氛和光回第 1 步,距离和怪物分布回第 2 步,尺寸、穿模、碰撞回第 3 步。

第 1 步的产出:墓园的概念图,把苔藓前景、墓碑与火光、古祠和远处雾谷分成几层,后来成了美术复查的参照

第 2 步的产出:浮岛时期的顶视分区图,北在上,100 米一格,标出营地、门、主路和刷怪点

一条铁律:不在编辑器里手工挪东西

第 4 步由一个地图工具包完成,入口只有一个命令:

python run.py wilds terrain    # 离线生成地形、树和地被的撒点
python run.py wilds level      # 建关卡、导入地形
python run.py wilds scatter    # PCG 撒巨树和地面植被
python run.py wilds dress      # 营地、墓园、刷怪点的摆设
python run.py wilds nav        # 导出导航网格
python run.py wilds mapdata    # 写服务器用的地图数据
python run.py wilds verify     # 自动验收

关卡里的一切都从三个文件生成:布局(02_layout.json)、素材清单(03_assets.json)和工具包代码。看到哪里不对,AI 改的是这三样,然后重跑对应步骤,不在编辑器里手工拖。这条规矩的好处是可重复:任何时候删掉关卡重建,得到的都是同一张图;工具包改了以后,用北林做回归,地形和撒点要和上一版逐字节一样,328 件摆设的位置差必须是 0。

这些步骤后来也写成了一份 skill(操作手册),新开的智能体读一遍就知道怎么做地图,不用从头讲。

验收不靠“看起来还行”

AI 很擅长说“已完成”。所以每一步都配了能自动跑的检查:

  • 地面核对:随机 300 个点,比较编辑器里射线打到的地面和生成器算出的地面,误差要在 ±10 厘米内。
  • 可达检查:从营地出发,每个功能点和刷怪点都得走得到。
  • 数据校验:服务器的地图数据过一遍校验,0 错误。
  • 查洞:导航网格逐格和地形对比,有没有能掉下去的地方(后面会讲为什么要加这一项)。
  • 机器人:重启服务器后放 3 个机器人,把地图的每道门走一个来回。
  • 原画对照:按概念图的机位在游戏里拍同一个角度,左右并排。

最后一条最重要。早在第二天,我们就在记录里写下:通行验证通过,不等于视觉还原通过。

森林是怎么长出来的

10 月 28 日:浮岛样板。 先做了一座约 1.2 × 0.9 千米的浮岛:2751 棵银冷杉、7 万多株蕨类苔藓倒木,四周 84 块破碎悬崖。当晚扩到约 2 × 1.5 千米,接进联网游戏当“荒野”,机器人走两道门 3/3 成功。

第一天最早的浮岛:先用彩色柱子标出营地、门和刷怪点的位置,再往上长东西

10 月 29 日:浮岛改成大陆。 画全世界地图册时发现,浮岛和世界观对不上:世界是一块破碎的大陆,中心连成一片,外围才裂开,不是到处都是倒锥形的空岛。北林按这个重做成约 5 × 4 千米的大陆森林。

改成连续大陆后的第一版:林子有了,雾、边缘和地貌层次还很粗糙

10 月 30 日:断层台地。 照着概念图,地形换成被雾谷切开的断层台地:先出等高线图确认,再生成。地形网格约 156 万个三角形,主路 3.8 千米。然后是一整天的崖壁:横向岩层、崩塌缺口、崖边大石、谷里 1400 团体积雾。晚上把树改成分层的森林,最多时约 5 万棵,最老的冷杉高 100~127 米。

雾放进谷里,近岸、石峰和对岸拉开了层次

树分成高低不同的几层,林缘也有了变化

10 月 31 日:边界和规则。 树根不再伸出崖外,崖线加碎口;游戏里按 F3 显示坐标,截图时能直接报位置。加了边界墙和“迷雾深处会死”的规则。

11 月 1 日:补洞和三轮美术复查。 加了换地图的加载画面,补掉地图里两千多个竖井,然后美术总监连审三轮,直到放行。

碰到的问题,和怎么解决的

1. AI 做出来的东西太“规整”

第一版崖壁是从台地到谷底一格直落,只看得到一条条竖棱,像切开的蛋糕。解法是把崖顶外 160 米重新算一遍:软硬相间的岩层、台阶、冲沟,约两成崖边整块塌成缺口,崖脚堆上倒石锥。

第一版缺口有副作用:把通往一个怪物巢穴的窄台地塌断了。后来规定缺口只能在两边都够宽的台地上塌,生成地形时先离线检查每个功能点能不能从营地走到。

崖边摆什么也走了弯路。先试着把素材包里的大石头放大三四倍沿崖贴,结果颜色浅、形状圆,像一排鼓包;又试了工程里现成的层状崖块,贴图放大后发糊。最后的做法是让地形自己按节理切出 10~25 米的岩块,块与块之间留竖直裂缝;大石头只用来做崖顶边缘的立面,埋进土里,地面用缓坡和植被把石根盖住。

崖壁的三个阶段(机位不同):规整的竖向挤出 → 岩层和崩塌缺口 → 用工程里的崖石接住地表

2. 看到的地面,和踩到的不一样

第一天就碰到:人的腿陷在地里,栅栏和人浮在半空。原因是地形用了 Nanite,而碰撞是从 Nanite 的自动简化模型生成的,和看到的表面差了十几到一百多厘米。改成简化模型保留全部三角形后,随机 300 个点的误差回到 ±9 厘米以内;后来的地形每次重建都在 ±0.1 厘米。

类似的还有:PCG 撒的树明明打开了“默认碰撞”,生成出来却是“无碰撞”,人能直接穿过去,要直接指定 BlockAll 才行;放大 6 倍的树桩只有一根胶囊碰撞;大帐篷干脆没有简单碰撞。这类问题全部归到第 3 步“比例尺图”里,用脚本量一遍、列成问题清单,而不是等试玩撞上。

3. 地图里冒出两千多个竖井

试玩时发现:离地图边缘还远,林子里就有一个个四壁垂直、深不见底的方坑。

一开始怀疑是模型破了洞。查下来,网格除了外框以外没有一条开口边——问题出在高度场本身。崖壁算法几乎是直上直下的,所以只要有一两格宽的谷,四周的崖壁一落就是几十上百米,在网格上就是一口约 8 米宽的方井。全图离线统计出 2069 块这样的窄缝和封闭坑,大部分在崖边 20 米以内。来源拆开看:大头是高度场本身(1503 块),崖边碎口 469 块,崩塌缺口 97 块。

还有更隐蔽的一类:崖边大石只把台地地面垫高,跨在坑口上的那部分底下是空的,从上面看是实地,走上去会掉下去。

解法是一组按宽度判断的规则:放不下 20 米见方的缝抬成台地;窄口后面的小湾抬平;塌不够宽的缺口干脆不塌;石块底下和石块之间的缝封死;还剩的深坑垫成最深 3 米、走得出来的浅凹地。朝外敞开、和外面雾谷连着的崖湾属于正常的悬崖,保留。

验收方式也换了:编辑器里打射线大约 175 毫秒一个点,太慢;改成拿 1.25 米一格的导航网格逐格和地形对比。修之前 192301 格比地面低,修之后 0 格。

同一个检查点:左边是修之前的竖井,右边补平后的地面,外侧正常的悬崖保留

4. 走出地图,一直往下掉

试玩时从南边界走出了地图,然后一直往下掉,停不下来。原因是台地一直延伸到地图边上才被截断,边缘外面什么都没有。

修法分两层:地图边上 250 米一律是雾谷,四周再立一圈看不见的墙。同时加了一条游戏规则:迷雾深处会死。掉进雾谷,每秒掉 25% 生命,大约 4 秒死亡,在营地复活,墓碑留在掉下去之前最后站过的实地上,回去捡东西不用跳谷。谷底的雾也加浓了,从崖边往下只能看到一片白,只露出石峰的尖。

5. 截图会骗人

这是 AI 做视觉工作时最容易被坑的地方。

火消失了。 美术总监前两轮审查的截图里,营地篝火和墓园蜡烛几乎看不到火焰,画面角落还常有 Lumen 缓存超出的红字。我们一度以为是灯光和缓存设置的问题。最后程序查到:编辑器不在前台时,UE 会把它限到每秒约 3 帧(bThrottleCPUWhenNotForeground),火焰粒子留不住,Lumen 也来不及收敛。AI 在后台驱动编辑器,编辑器恰好永远“不在前台”。关掉这个限制、在 Simulate 模式里拍,火回来了,红字也没了,缓存大小一点没动。

天上有三块石头。 截图里,天上一直飘着三块石头。查下来是前一天试崖边石时临时放进关卡的,工具包里没有任何一步负责清它们。现在关卡、环境几个步骤一开头就会清掉这类试摆文件夹。

存盘没存进去。 游戏客户端开着、并且进过这张图时,编辑器的“保存”不报错,但文件根本没写进磁盘。工具包现在每次存盘后都核对文件修改时间,没变就报错。

6. 换地图卡住

从别的地图走进北林,画面会冻住好几秒。改成先在后台把新关卡载进内存,游戏照常画加载画面(地名、安全等级、进度条和百分比,背景用这张地图的概念图),载完再切换。北林后台载入约 5~7 秒,真正卡住的只剩约 1 秒,这 1 秒由单独的线程画同样的画面。中间踩了一个崩溃:预载的世界如果登记成“游戏世界”,切换时会被引擎的世界泄漏检查直接拦下。

换地图时的加载画面,背景是压暗的北林概念图

7. AI 用电脑,也要守规矩

AI 和人用的是同一台电脑,AI 的操作可能打断正在用电脑的人。解决办法是几条硬规矩:

  • 不模拟键盘鼠标。 电脑上可能有人正在用别的窗口,模拟的按键会打进去。看效果一律用编辑器视口截图。
  • 关游戏、重启服务器先问人。

8. 素材授权:NoAI

场景里的模型大多是在 Fab 上买的素材,其中不少带 NoAI 标记。我们的理解(项目决策 D057)是:可以放进游戏,AI 可以看包含这些素材的截图做检查,但不能把素材图或游戏截图喂给任何出图模型,也不能用来训练。所以概念图只用文字生成,不能“照着游戏截图改一版”。

还有一条美术上的规矩:光只来自真实的光源——篝火、火盆、灯笼、蜡烛、天光。第一天的浮岛上有凭空出现的紫色灯、蓝色灯和发光的雾,看起来很假,全部去掉了;墓园后来加的每一盏小暖光,底下都有一根真的蜡烛。

让 AI 审 AI:三轮美术复查

洞补完、通行全过以后,画面还是和原画差很远。这一步我们交给美术总监:它进编辑器按概念图的机位拍图,逐项对比,写审查报告,每条写位置、现状、要改成什么、怎么验收。

第一轮指出:营地四顶帐篷沿栅栏均匀摆一圈,像展台;墓园没有主角;林子从空中看是一张同样厚的树毯。程序改了一轮。

第二轮判定补洞、林缘、营门和火光过关,但墓园变成了一片光秃的泥地,比改之前还空,林冠也还连成一片。返工清单写得很具体:墓园苔藓要盖住 55%~65% 的地面、裸土不超过 25%;主祠换成同一素材包里的拱门墙加坡顶,两件模型接缝高度都是 254.06,能对齐;疏林的林冠接受率从 0.45 压到 0.12~0.18;空地要按树冠边缘而不是树干位置留。

第三轮放行:林冠在 100 × 100 米的窗口里,密林中位冠盖 91%、疏林 42%;营地读得出两组帐篷;墓园有了拱门坡顶的旧古祠、台阶、残墙、苔藓和蜡烛。美术总监还发现,此前用来判断墓园构图的远机位压小了古祠、放大了空天,换成正常 1.7 米眼高后,古祠、墓碑和远处的崖壁雾谷能同框,所以没有为构图去搬整个墓园。

墓园的三轮:草和蕨把碑遮住 → 碑露出来了,地面却空了 → 补回苔藓、古祠、残墙和蜡烛

第三轮的墓园,正常眼高:碑、台阶、蜡烛、古祠和远处的崖壁同框

林冠疏密:左边是一整片树毯,右边按树冠边缘留出了疏林和空地

营地:帐篷从沿栅栏散开摆一圈,收成两组生活区,物资归到各组

神木也是同样的思路:倒下的巨树被近处的枝叶挡住,读不出来。美术总监没有让程序继续放大模型,而是在观察方向上清出一个视线窗口,让根盘、倒干和供奉物能顺着看过去。

神木:清出观察方向的遮挡,而不是继续放大模型

还没做完的也写在报告里:外崖的局部轮廓、伐木营从眼高看不到崖下的雾谷、墓园所在的台地比原画平。原画是目标,不是已经达到的状态。

概念图(左)和第三轮的游戏实景(右):古祠的尺度、平地和近处的深谷,差距都还在

几点体会

  • 让 AI 改文件,不让它改场景。 所有东西都从布局和工具包生成,出了问题能回退、能重建、能回归。AI 在编辑器里手工拖的东西,下次重建就没了,也没人知道它拖过什么。
  • 每一步都要能自动验收。 “看起来没问题”对 AI 没有约束力。地面误差、可达性、查洞格数、冠盖率这些数字,才是它真正会去对齐的目标。
  • 截图对照原画,而且要怀疑截图本身。 同一个场景,编辑器在不在前台、机位高一点低一点,结论可能完全相反。
  • 规矩要写下来。 不模拟按键、光只来自火源、素材不喂模型,这些写进 skill 和记忆里,新开的智能体一上来就知道。

一些数字

项目数字
项目第一个提交2026-10-28 02:37
到 11 月 1 日的提交数117
地图工具包40 个文件,约 1.7 万行(通用,不只服务北林)
北林大小约 5 × 4 千米,主路 3.8 千米
补掉的竖井2069 块;查洞漏格 192301 → 0
树最多时约 5 万棵,疏密调整后主林 18519 棵
美术复查3 轮

接下来

  • 把伐木营的视线窗口和外崖轮廓做完。
  • 用同一套流程做下一张地图:边境原野。
  • 在打包后的客户端里做一次完整的性能测试。

这篇文章由 AI 根据工程的提交记录、设计文档和审查报告整理写成,截图来自开发过程中的编辑器和游戏画面。

返回笔记列表
TOP