用Antigravity+Blender MCP快速搭建智慧仓储数字孪生场景
上周客户催着要一个能放进汇报 PPT 的智慧仓储演示场景,三天内必须出“能看”的版本。手头既没有现成的 BIM 模型,也不想花两天时间手工摆货架,于是把 Antigravity 和 Blender MCP 这套组合拉出来做了一次进阶实战。效果比预期好得多:Agent 能听懂“建一个 60 米乘 50 米的仓库,排 6 列双深货架,主通道留 4 米”这类需求,直接驱动 Blender 批量生成整个数字孪生场景。
这篇文章是上一集的续篇,重点从“用 Agent 生成几个孤立模型”推进到“用 Agent 搭建完整可用的仓储数字孪生场景”。适合两类人:一是要做数字孪生演示、方案汇报的工程师,二是想摸清 AI Agent 生产力边界的技术爱好者。我会把从环境配置、需求建模到最终导出的完整实战过程拆开讲,包括我在项目里踩过的坑和验证过的参数。
1. 整体思路:为什么用 Antigravity 驱动 Blender 搭数字孪生
1.1 从“手工画场景”到“参数化生成”的思路转变
传统的 3D 智慧仓储场景搭建流程我很熟:建模师在 Blender 里逐个创建货架,复制阵列,手动调整位置,配材质,打灯光,最后导出给前端。一个 3000 平米的仓库,光货架就有几百组,每组 5 层 6 列,手工操作少说要两天,而且最痛苦的是改方案——客户说“通道宽度从 4 米改成 3.5 米”,意味着整个排布重新推倒再来。
换成 Antigravity 加 Blender MCP 的工作流,核心变化在于:把“画图”变成“写参数”。先在 JSON 里定义仓库尺寸、货架规格、通道宽度、分区规则,然后让 Agent 写 Python 脚本,通过 MCP 工具在 Blender 里批量执行。修改方案时只需要改 JSON 里的几个数字,重新跑一遍生成逻辑,整个场景自动重建。实测下来,同样的仓库建模,第一次跑通用了半天,后续参数调整基本在几分钟内完成。
这套思路的本质是参数化生成,对数字孪生场景尤其适用,因为数字孪生本身就要求场景能跟随业务数据变化而变化。如果每次数据更新都靠人工调模型,那就失去了“孪生”的意义。
1.2 智慧仓储数字孪生到底需要哪些“零件”
在让 Agent 动手之前,先得把场景里要出现的东西列清楚。数字孪生不是把仓库外墙建出来就完事,而是要让业务对象在三维空间里有对应关系。我这次的项目清单包括:
- 仓库主体:地面、墙体(或围栏)、出入口、分拣区
- 存储单元:货架、托盘、料箱
- 移动设备:AGV 小车、叉车(演示用简单几何体即可)
- 路径与区域:主通道、作业通道、安全禁入区
- 数据映射:库存状态通过颜色编码体现在料箱上
分层也很重要。最底层是物理结构,中间是设备与物料,最上层是数据可视化。如果未来要接入真实系统,可以在最底层对接三维结构光相机或点云扫描数据,把现实世界的货架尺寸高精度还原;中间层对接 WMS 库存数据,让每个料箱的库存状态实时驱动颜色变化。这次实战我重点做中间层和上层,底层用标准规格参数生成。
2. 环境部署:把 Blender MCP 服务接入 Antigravity
2.1 Blender 侧必须做好的三件事
Blender MCP 是 GitHub 上的开源项目,本质是一个 MCP 服务器加一个 Blender 插件,插件在 Blender 里开启 Socket 服务,MCP 服务器把 AI 客户端的工具调用转发给插件,由插件通过bpy操作 Blender。我用的版本基于 Blender 4.x 验证,3.x 大概率也行,但建议直接上 4.x。
部署时注意三点。第一,把插件文件夹放到 Blender 的 addons 目录,然后在偏好设置里启用。第二,在 Blender 的插件面板里找到 Blender MCP 的启动按钮,点击后它会在本地起一个 Socket 服务,默认端口 9876,启动成功后面板上会显示监听状态。第三,MCP 服务器需要独立运行,我习惯用 Python 虚拟环境加uvx方式启动。
启动 Blender 侧的 MCP 服务后,不要最小化窗口就以为万事大吉。我踩过一次坑:Blender 窗口在后台运行久了会进入某种低功耗状态,Socket 连接变慢,Agent 那边的工具调用延迟明显增大,看起来就像“卡死”。最好把系统休眠关掉,或者至少让 Blender 窗口保持活跃。
2.2 Antigravity 侧配置 MCP Server
Antigravity 的 Agent 工作区支持添加 MCP Server,在 Agent 配置界面里选择添加服务器,类型选择本地命令方式。命令和参数如下:
uvx blender-mcp不同系统下uvx的路径可能不一样,Windows 下如果直接写uvx找不到命令,就要写完整路径,比如C:\Users\你的用户名\.local\bin\uvx.exe。配置完成后重启 Agent 会话,MCP 工具列表里会出现execute_code、create_object、modify_object等能力。
这里有个容易误判的点:工具列表加载成功,不代表能立刻操作 Blender。MCP 工具加载成功只说明客户端和 MCP 服务器握手成功了,Blender 插件那边的 Socket 服务还连着才开始干活。我的习惯是配置完成后先用一个最简单的create_object创建一个方块,确认 Blender 视口里真的出现了东西,再进行场景搭建。
2.3 先统一“语言”:单位、原点与轴方向
这是整个实战中最重要的前置约定,没有之一。Agent 生成的脚本是按坐标计算位置的,如果单位、原点、轴方向没有定死,货架会出现在莫名其妙的地方,甚至嵌入地面。
我在项目里做了三个约定。第一,Blender 场景单位设置为米,长度单位选“米”,这样生成一个 2.7 宽的货架实例,实际就是 2.7 米。第二,世界原点定为仓库的西南角,所有货架、通道、设备的坐标都基于这个原点计算。第三,Z 轴向上,建筑高度沿 Z 轴增长,货架层高计算直接用 Y 轴层数乘以层间距。
为了防止 Agent 在生成过程中“忘了”这些约定,我让它在脚本里先跑一个verify_scene函数,检查单位、原点、起始坐标,然后输出结果。Antigravity 的 Agent 可以通过工具拿到这些反馈文本,它确实会依据检查结果调整后续脚本,不是装样子。
3. 从需求到场景:3000 平米仓库的完整搭建过程
3.1 把仓库需求写成“需求 JSON”
给 Agent 下需求时,最好把信息结构化,而不是让它在对话里猜。我按仓储行业的通用参数建了一份需求 JSON,Agent 的任务就是解析这份 JSON 并完成场景搭建。
{ "warehouse": {"length": 60, "width": 50, "height": 9}, "shelf": { "columns": 6, "levels": 5, "unit_width": 2.7, "unit_depth": 1.1, "level_height": 1.8, "double_depth": true }, "layout": { "main_aisle": 4.0, "work_aisle": 3.5, "edge_margin": 0.8, "double_row_pair": true }, "sku_zones": [ {"name": "A", "location": "north", "color": [0.2, 0.6, 0.9]}, {"name": "B", "location": "south", "color": [0.9, 0.7, 0.1]} ] }参数含义:仓库全长 60 米、宽 50 米、高 9 米;货架每排 6 列、5 层,单货位宽 2.7 米、深 1.1 米(双深就是 2.2 米),层高 1.8 米;主通道 4 米,作业通道 3.5 米,仓库四周留 0.8 米安全边距。这些数字都是仓储设计里常用的范围,比如 4 米主通道是 AGV 双向通行的安全宽度,不是随便拍的。
JSON 写好后直接粘贴给 Antigravity 的 Agent,要求它一句一确认:先解析 JSON,再规划排布逻辑,最后动手生成。实测下来,Agent 对这类结构化任务的完成度明显高于口语化指令。
3.2 让 Agent 写一个可复用的 build_shelf 函数
批量生成的核心不是让 Agent 写几千行重复代码,而是让 Agent 写一个足够好的“零件函数”,然后用循环去调用。我在提示词里要求 Agent 先设计build_shelf(x, y)函数,函数的职责是:在给定坐标处生成一组双深货架,包括立柱、层板、托盘和料箱。
Agent 产出的代码思路值得参考,它把逻辑拆成了网格和数据两层。网格用平面裁切,层板用薄立方体,托盘用标准化尺寸做实例,料箱放在托盘上。这样生成的模型面数可控,视觉效果也够用。双深货架的排布逻辑是:两排货架背靠背,共用中间通道,开口朝向两侧作业通道。
import bpy def build_shelf(x, y, columns=6, levels=5, unit_width=2.7, unit_depth=2.2, level_height=1.8): frame_width = columns * unit_width frame_height = levels * level_height bpy.ops.mesh.primitive_cube_add(size=1, location=(x + frame_width/2, y + unit_depth/2, frame_height/2)) obj = bpy.context.object obj.scale = (frame_width, unit_depth, frame_height) # 简洁起见省略材质与面细分细节,实际运行可直接复用实际执行时我不会一次生成全部货架,而是每排货架调用一次build_shelf,边生成边检查坐标是否越界。生成 6 排双深货架后,让 Agent 输出所有货架的位置列表,我再人工核对一遍有没有跟通道重叠。
3.3 用循环和实例化铺满整个仓库
单排货架函数调通之后,铺满仓库就是循环工作。我让 Agent 按仓库长度方向排列货架组,排布规则是:每两组双深货架之间留 3.5 米作业通道,每隔 4 组在主通道位置断开,形成区块化布局。
这里有一个重要的性能教训:不要用bpy.ops在循环里反复复制带高面数的物体,否则 Blender 的文件会迅速膨胀,操作也变卡。正确做法是用 Collection 实例化,先创建一组货架作为模板实例,然后用collection.instance.new()循环创建实例。这样所有实例共享一份网格数据,内存占用和文件大小都低得多。
我实际让 Agent 生成的场景里,3000 平米仓库包含 6 排双深货架、每排 10 组、每组 5 层 6 列,货位总数约 3600 个。如果每个货位都是独立网格,文件会到几百兆,用实例化之后源文件只有 80 多兆,导出 glTF 时再把不需要交互的实例合并成几个大网格,前端加载完全没问题。
AGV 路径处理上,我没有直接建模小车,而是在地面用平面裁切出主通道区域,通道边缘加了一圈白色警示线,这是数字孪生场景里很抢眼的小细节。警示线的生成逻辑很简单:沿着通道边缘创建一组细长方体,宽度 0.1 米,材质用 emissive 白色。Agent 写这个逻辑很快,视觉提升却很明显。
3.4 库存数据可视化:让场景“会说话”
纯 3D 场景只能叫模型,能反映业务数据才叫数字孪生。这一步我让 Agent 给每个料箱创建材质,并根据库存百分比分配颜色:库存大于 60% 用绿色,30% 到 60% 用黄色,低于 30% 用红色。
实现方式是在生成货架时同时生成一份仓位数据表,每个料箱对应一个仓位编号。然后 Agent 写了一个批量上色函数,遍历所有料箱,读取库存比例,动态切换材质颜色。
def paint_by_inventory(obj, ratio): if obj.get("inventory_ratio") is None: return if ratio < 0.3: color = (0.8, 0.2, 0.2, 1) elif ratio < 0.6: color = (0.9, 0.7, 0.1, 1) else: color = (0.1, 0.7, 0.3, 1) mat = bpy.data.materials.new(f"inv_{obj.name}") mat.diffuse_color = color obj.data.materials.clear() obj.data.materials.append(mat)从远处看,整个仓库的库存状态一目了然:南区偏黄、北区偏绿、几个角落飘红。这种可视化效果放进汇报 PPT 里,比十页文字表格都直观。
4. 实战里绕不开的坑:连接、报错与优化
4.1 MCP 工具列表显示不出来,怎么排查
这是新人最容易卡住的地方。MCP 工具列表为空,原因通常是这几个,按顺序排查能省很多时间。第一,Blender 插件里的 Socket 服务没启动,或者端口被占用,查看 Blender 插件面板的日志能确认。第二,uvx blender-mcp的路径不对,Windows 下尤其常见,用终端单独跑一遍能直接看到报错。第三,Antigravity 的 Agent 配置改了之后没重启会话,MCP Server 是会话级加载的,配置变更必须重新开一个会话。
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 工具列表为空 | Blender 插件 Socket 未启动 | 检查插件面板监听状态 |
| 工具列表加载成功但操作无响应 | Blender 窗口休眠 | 关闭系统休眠,保持 Blender 活跃 |
| 启动 Agent 即报错 | MCP 命令路径错误 | 终端手动执行uvx blender-mcp验证 |
| 模型生成位置错乱 | 单位或原点约定未生效 | 让 Agent 输出坐标,人工核对 |
4.2 Agent 的“隐身操作”是最难防的问题
Agent 通过 MCP 执行脚本时,它自己是看不到 Blender 视口的。它写出来的代码在逻辑上可能没问题,但实际执行时容易出现模型重叠、悬空、嵌入地面这类问题。我的做法是给它加一个“眼睛”:让 Agent 每完成一批操作,就调用查询函数,列出当前场景里所有对象的位置和尺寸,把结果存成文本,它自己看到之后会自动调整。
这种方式在实战里非常管用。比如有一次 Agent 生成完第 3 排货架时,查询结果显示 Y 坐标跟第 2 排只差 1.9 米,明显违反了 3.5 米通道约定。Agent 看了这个输出,自己就在下一步修正了循环参数的增量值。
另外,把任务拆小也是一个有效的办法。与其让 Agent 一句“生成整个仓库”,不如拆成“生成第 1 排货架 → 检查 → 生成第 2 排 → 检查”。虽然对话次数变多,但每次都能及时发现问题。
4.3 场景文件和导出 glTF 的性能问题
场景搭建完成后,还要导出给前端做 Web 端数字孪生展示。这一步最容易翻车的是文件导出失败或网页加载卡顿。经验是导出前做三件事:删除场景里所有未使用的数据和材质、将实例化的货架组应用变换(把位置旋转归一到世界坐标)、用 glTF 导出时勾选 Draco 压缩。
Blender 自带的 glTF 导出对实例化支持很成熟,但导出文件时要注意勾选“使用 Draco 网格压缩”,这个选项能把网格数据压缩到原来的四分之一左右。我导出的 80 多兆 Blender 源文件,压缩后 glTF 只有 20 多兆,放到前端工程加载速度从十几秒降到三四秒。
另一个容易忽略的问题:如果场景里有些物体导出后不需要参与交互(比如地面、墙体、纯装饰的警示线),可以在 Blender 里把它们合并成单个网格再导出,前端渲染的面数压力会小很多。合并网格的操作可以用 Agent 写脚本自动完成,一句“把名为 Ground 和 Wall 系列的对象合并成一个”就行。
这个场景还可以继续扩展。比如接入实时库存 API 后,让脚本定时读数据刷新料箱颜色;或者加一个 AGV 沿路径行走的简单动画,让演示画面更生动。踩过几次坑之后,我最大的体会是:跟 Agent 协作,别急着让它一把梭,而是把需求拆成小步骤,每步都给它一个可以自我校验的反馈机制,这样既稳定又高效。