做智慧仓储数字孪生,最痛苦的往往不是业务逻辑,而是“把一堆表格数据变成看得见、摸得着的那个3D世界”。我们团队过去处理这类项目,一半时间耗在手动建模上:货架一个一个拖、库位一个一个命名,改一个位置要同步半天;另一半时间耗在环境切换上——Blender里建模,前端代码里做可视化,两边数据口径经常对不上。一个库位变更,映射过去要花一整天。
这篇文章记录我们最近一次比较顺利的尝试:用Antigravity这个 AI Agent 开发环境,配合Blender MCP这套让 AI 远程操作 Blender 的协议桥梁,把“3D 智慧仓储数字孪生”从零到一搭起来。标题里写的是“上”,所以这一篇先把场景建模、数据联动和排查经验讲透,业务规则、交互面板、Web 端发布这些留给下半篇。
这篇内容适合两类人看:一类是准备做数字孪生但工具链还没想清楚,正纠结于 Three.js、Unity 和 Blender 怎么选;另一类就是被 Blender 里大量重复建模折磨,想找一个“说人话就能建模”的方案。我会尽量把每一步怎么做、为什么这么做讲清楚,算是一份可以照着抄作业的实战记录。
1. 项目整体设计与思路拆解
1.1 智慧仓储数字孪生的核心目标
先给“智慧仓储数字孪生”下个务实定义:在三维空间里,把现实仓库的货架、库位、货物、搬运设备还原成数字模型,再让这个模型的每一个对象和仓库管理数据库里的库位状态、库存数量、进出库事件保持实时一致。
听起来很“概念”,落到仓库现场其实是几个很实际的需求:
- 库位状态可视化:哪些库位空闲、哪些占用、哪些货物久置未动,一眼就能看出来。
- 库存分布可视化:某个 SKU 存在哪个巷道、第几层,不用翻表格。
- 出入库过程推演:AGV 从哪个库位取货、走什么路径、到哪个月台,可以在数字空间里先跑一遍。
- 异常预警:低库存、满箱、超期存放,在 3D 场景里用颜色/动画标出来。
这些需求有一个共同前提:必须有干净、规范、可以批量生产的 3D 场景模型。以前我们卡就卡在这个前提上。手动建模的案例如你所见,一个标准仓库几百个库位,纯手工做,一周起步;更不用说后续数据映射还需要给每个对象命名、绑定材质——重复劳动强度极大。
1.2 为什么选 Antigravity + Blender MCP,而不是传统建模流水线
先讲选型逻辑。市面上面向数字孪生的 3D 方案大致分三类:
- 游戏引擎路线(Unity / Unreal):适合最终要发布成可交互应用的项目,但建模资产前期仍然要导入,场景搭建和调整在“引擎编辑器”里做,并不天然解决建模效率问题。
- Web 渲染路线(Three.js / Cesium):适合做面向浏览器的可视化,但建模和渲染被绑在一起,场景复杂后代码量爆炸,而且和 Blender 资产之间的工作流需要额外打通。
- DCC 工具路线(Blender):建模、材质、灯光、动画都在一个软件里搞定,输出资产干净,但纯人肉操作效率太低;纯写 Python 脚本效率高,可调试成本也不低。
我们的最终目标其实是“Blender 生产资产 + 后续 Web 展示”。所以怎么提高 Blender 侧的生产效率,就成了整个项目第一个要解决的问题。这才把目光落到Antigravity + Blender MCP这个组合上。
Antigravity是一个 AI 原生 IDE,核心不只是一个编辑器,而是一个能自动写代码、执行命令、管理文件的 Agent 工作区。你可以直接在里面下指令:“帮我在项目里生成一个仓库数据同步脚本”,它会自己建文件、写逻辑、跑测试。这种模式特别适合数字孪生这类“代码 + 数据 + 3D 资产”混合型任务,因为中间有大量胶水代码,以前是程序员手工写,现在可以交给 Agent 快速铺出来。
Blender MCP则是把 Blender 的 Python API 通过 MCP 协议暴露成标准工具集。MCP(Model Context Protocol)可以理解为 AI 模型与外部软件之间的“标准插口”——它定义了 AI 调用外部工具时的消息格式和调用规则。装上 Blender MCP 之后,Antigravity 里的 Agent 可以直接说“在场景里创建一个 20x30 米的地面”,它会自动转换成一个对应 Blender 命令,Blender 场景里立刻出现这个地面。
组合在一起的效果是:需要写代码的重复建模、批量改材质、数据同步这类工作,都用对话完成;真正需要设计判断的部分,比如布局、视觉效果、命名规范,由人来定。我们试跑之后发现效率提升非常明显,原来一周的建模工作量,压缩到一天以内。
2. 工具选型解析与基础环境搭建
2.1 Antigravity 上手:Agent 模式和主要界面概念
我先说结论:如果你想完整复现这套流程,建议先从 Antigravity 的 AI Agent 能力入手熟悉产品。
Antigravity 的实际体验和传统 IDE 差别很大。普通 IDE 是你写代码、它补全;Antigravity 更像一个工程执行 Agent:你给它一个任务描述,它自己读项目结构、生成文件、执行命令,甚至能根据报错自动修代码。整个交互在一个会话(Session)里完成,你可以一直追加需求,它会在项目里连续干活。
登录之后,我第一次实际用就踩了一个很常见的坑:账号资格校验失败。当时界面上直接弹了“eligibility check failed”和“sorry, this account is ineligible to use antigravity”之类的提示,也就是说账号当前不满足使用条件。这种资格校验在海外 AI 服务里很常见,一般和注册邮箱类型、所在地区、服务条款适用性有关。遇到这个提示,能做的是检查账号注册信息是否完整、换用符合服务范围的邮箱,并通过官方渠道了解该工具当前适用的地区和条款。不要相信任何“强行注册”“修改地区信息”的偏方,不仅可能让账号进入风控,后续数据也完全没保障。我们团队的正式账号是走官方申请流程后正常开放的,后续全程稳定。
新版进去之后,主要概念就三个:
- Agent / 任务会话:你描述需求,它干活。比如“帮我新建 Python 脚本目录”,它真的会动手建。
- Rules(规则):给 Agent 设定工作习惯,比如“所有脚本必须包含异常处理”“禁止删除生产文件”。建议一开头就配好,后面省很多事。
- MCP 配置:把外部工具(在这里是 Blender MCP)注册进来,Agent 就能调用。
2.2 Blender MCP 的工作原理
Blender MCP 本质上解决一个问题:怎么让 AI Agent 安全、标准地操控 Blender。
Blender 自带强大的 Python API(bpy),如果你自己能写代码,完全可以直接写脚本操作场景。但 AI Agent 不能靠“猜”来调用 bpy,它需要一套明确的、封装好的工具清单——比如“创建盒子”“复制对象”“设置材质”“摆相机”。Blender MCP 做的就是这件事:它起一个本地服务,把常用的 Blender 操作封装成一个个工具,暴露给 AI Agent。
架构上分两部分:
- MCP Server 端:负责接收 AI Agent 发来的请求,比如“create_box”,把它转换后通过本机端口转发给 Blender。
- Blender 插件端(Addon):安装在 Blender 内部,监听同一个端口,收到请求后直接操作当前场景。
用生活里的例子理解,就是:AI Agent 是客户,Blender 是厨师,MCP Server 是传菜口,Blender 插件是灶台。客户点菜,传菜口按标准格式下单,灶台负责做菜,做完再按原路端回去。
我们在选型时比较过两个替代方案。一个是直接用Blender Python 脚本文件,让 Agent 生成一个 .py 然后手动在 Blender 里打开执行。这个方案的问题在于调试循环太慢——Agent 写错了,你只能在 Blender 界面里看报错,再回来改提示词。另一个是Socket API 透传,把原始 bpy 命令原样发给 AI,等于让 AI 硬编码调用 API,效率低且容易出错。Blender MCP 的方案好在“工具封装”这层,AI 不需要记住每个 API 的参数细节,只需要理解工具语义。
2.3 环境搭建的详细步骤
先说版本结论:Blender 建议用当前稳定主版本(比如 3.6 LTS 或 4.x 稳定版),Python 环境建议用 3.10 以上。MCP 相关社区版本迭代比较快,但整体安装路径是固定的。
第一步,装 Blender 插件。在 Blender 的“编辑 → 偏好设置 → 插件 → 安装”里,选中下载好的 blender-mcp 插件包,然后启用。启用后,Blender 的右侧工具栏(N 面板)会出现 MCP 相关的面板,上面有服务启动开关、端口号、连接状态。
第二步,启动 MCP Server。社区常见的做法是使用 uv/uvx 来运行一个叫 blender-mcp-server 或同名工具的服务。命令大概长这样:
uvx --from blender-mcp-server blender-mcp-server启动后只要终端显示“Server listening on ws://127.0.0.1:端口号”,并且 Blender 插件面板里的连接状态变成了绿色/已连接,说明两端已经通了。端口默认一般是 7777 或 8000,具体看你下载的版本说明,两边的配置必须完全一致。
第三步,在 Antigravity 里注册 MCP Server。打开项目的 MCP 配置入口,找到 mcpServers 配置项,填成这样:
{ "mcpServers": { "blender": { "command": "uvx", "args": ["--from", "blender-mcp-server", "blender-mcp-server"] } } }保存后刷新配置,正常情况下你会看到一串工具列表,像 create_box、create_material、set_camera、select_object 这类。看到工具列表就说明 Antigravity 已经能驱动 Blender 了。
提示:注册 MCP Server 时,Antigravity 端保证
uvx命令能被找到很重要。如果提示找不到命令,最简单的方式是用 which uvx 拿到绝对路径,写进 command 字段。
3. 3D 智慧仓储场景建模全流程
3.1 先把规划图纸变成建模参数
任何建模任务,第一步都不是动手建,而是定尺寸和坐标系。我们按一个中小型电商仓来做:仓库主体 30 米宽、20 米深;里面放 5 排货架,每排 8 组库位,双面货架,每组分上下两层;通道宽度统一 2.5 米,方便 AGV 走;仓库一侧设收货区,另一侧设出库月台。
Blender 默认单位是米,我们就用米作为统一单位。所有对象的命名按类型_区域_行_列走,比如shelf_A_01_L1表示 A 区域第 1 排第 1 列货架的 L1 层,floor_ground是地面,zone_receive是收货区。为什么命名这么重要?因为数字孪生要做的数据映射,本质靠每个模型的object name作为唯一 ID。名字一旦乱,后面数据对不上就是灾难。
在动手前,我习惯先在项目里放一个 layout.json,记录每个关键区域的坐标和尺寸。这不是浪费功夫,而是为了让 Antigravity 的 Agent 在生成模型时有据可依,而不是每次靠“猜”。
3.2 用自然语言让 Agent 生成基础结构
环境通了之后,真正的建模过程非常像“和一位懂 Blender 的同事对话”。我实际发出的第一个指令是:
“请在 Blender 中创建一块地面,尺寸 30x20 米,位置在原点,名称为 floor_ground,默认灰白材质。”
Antigravity 收到后,会自动调用 Blender MCP 的create_box工具,传入长宽高、位置、名称参数。几秒钟后切到 Blender 视口,一块地面就躺在场景中央了。第一次看到这个流程跑通的时候,我们团队成员都挺兴奋——这就是那个“说人话建模”的感觉。
但马上我就发现一个坑:一次性生成整个场景风险很大。如果直接让 Agent“创建整个仓库包括五个货架”,它可能会在同一时刻产生大量嵌套命令,任何一个参数错误都会让整个场景乱套;而且中间某个对象出错了,你在 Blender 里很难局部回退。所以我建议分批生成,一个区域一个区域来,每完成一块就在 Antigravity 里进行简单验证。
3.3 货架与库位的批量生成
基础结构完成后,进入最关键的货架和库位生成。这一步是重复劳动最重、也是 MCP 最能体现价值的地方。
标准货架建模,我们其实只需要两个基础几何体:立柱和层板。剩下的全部是“复制后按位置排列”。但几百个库位如果一个个说,AI 也会疲。正确做法是让 Agent 用循环自动生成。
我给 Antigravity 的提示词大致是这个风格:
“请用 Python 脚本方式生成一排双面货架,排号为 A。位置起点 x=0,z=0;每组库位宽 1.5 米,货架总长对应 8 组;每组上下两层,底层离地 0.1 米,层高 2 米;每个库位生成一组两个空物体作为锚点,命名格式 shelf_A_01_L1,并附加一个 1.2x1.5 米的立方体作为货物占位占位物体,默认透明材质。”
于是 Blender MCP 就会在后台把这个提示词转换成一段 Python 脚本,脚本通过循环一次性生成一排 8 组 16 个库位。命令里有一个我很看重的细节:用空物体做锚点。空物体在渲染里不可见,但它是一个独立的、稳定命名的对象,后面数据同步时,它就是挂接状态标签和动画的位置。没有锚点,后面想让某个具体库位高亮都没地方挂。
还要注意一个 Blender 操作习惯:循环生成时如果中途报错,Blender 里会自动切换为“追加模式”,前面成功生成的对象会残留。遇到这种情况我都是直接撤销到脚本执行前,然后把错误信息复制给 Antigravity 重新生成,不要手动一个个删,否则很容易删错。
3.4 材质、标签与基础灯光
货架结构建模完成之后,场景还是灰蒙蒙的,需要分配基础材质和灯光。这部分我同样交给 Agent,但规则定得更细:
- 地面:水泥灰色,粗糙度 0.8。
- 货架立柱:深灰色金属材质。
- 层板:浅灰色,粗糙度 0.4。
- 货物占位物体:白色半透明,方便后续按状态替换为红色、绿色。
我让 Antigravity“把材质统一建在一个名为 mats_lib 的集合里”,这样做的目的是后面数据同步脚本可以引用同一批材质,不会因为材质名不对而失效。
灯光方面用了一个环境纹理(HDRI),再把一个平行光当作主光源。这里没什么高深技巧,数字孪生场景最重要的不是电影感,而是信息读取得清楚,所以整体亮度要均匀,避免大块阴影遮住库位标签。
3.5 导入现成 AGV 和叉车模型
仓库场景里最好有搬运设备,这样拍起出入库动画才有代入感。AGV 不用从零建模,直接从开源 3D 模型库下载一个低多边形模型,导入到 Blender。导入之后一定有缩放问题——很多外部模型单位是厘米,导入米制场景会变得巨大。
我的处理方法是:选中模型后,让 Agent 调用set_object_scale工具,把缩放设为 0.01,然后再移动到指定路径。导入后的命名同样要按场景规则改成agv_01、agv_02,不然数据联动时会找不到对象。
4. 数据接入与数字孪生联动
4.1 数据链路设计
数字孪生不等于“3D 模型好看”,关键是那个孪生——模型必须和数据实时同步。仓储场景里,我们最需要同步的数据是库位状态。
这里我从业务上定义一套最小数据结构,一条库位记录长这样:
{ "object_id": "shelf_A_01_L1", "status": "occupied", "sku": "SKU-10086", "quantity": 42, "last_update": "2025-06-08 15:30:00" }object_id与 Blender 场景里的对象名一一对应;status有三种:empty(空闲)、occupied(占用)、hold(冻结/异常)。用颜色表示就是:绿色、红色、黄色。这就是数字孪生最朴素的联动逻辑。
数据从哪里来?真实项目里一般是 WMS 数据库、IoT 采集接口。我们在本地先用一个 JSON 文件模拟实时数据,让 Antigravity 的 Agent 写一个轮询脚本,每隔 5 秒读一次文件,再把变化同步进 Blender。
4.2 在 Antigravity 里生成并执行同步脚本
这一节是整篇文章操作浓度最高的地方。我直接说最终脚本的逻辑,然后讲它为什么这么设计。
脚本用 Blender Python(bpy)实现,核心步骤是:
- 读取
wms_state.json。 - 遍历每条记录,取
object_id,用bpy.data.objects.get(object_id)找到对应场景对象。 - 根据
status把场景对象中预设的“货物占位物体”材质切换成 green / red / yellow。 - 如果记录里带
sku,就把空物体锚点的自定义属性action_status更新为这个 SKU,方便后续做标签或筛选。
关键代码片段长这样:
import json import bpy STATE_FILE = "/path/to/wms_state.json" # 颜色材质在场景里预先创建好 materials = { "empty": bpy.data.materials.get("mat_empty"), "occupied": bpy.data.materials.get("mat_occupied"), "hold": bpy.data.materials.get("mat_hold"), } def sync_state(): with open(STATE_FILE, "r") as f: records = json.load(f) for rec in records: obj = bpy.data.objects.get(rec["object_id"]) if not obj: # 找不到对象时记录日志,不要中断整个同步 print(f"[WARN] object not found: {rec['object_id']}") continue # 库位下面的货物占位物体,统一命名为 <object_id>_holder holder_name = f"{rec['object_id']}_holder" holder = bpy.data.objects.get(holder_name) if holder and rec["status"] in materials: holder.active_material = materials[rec["status"]] obj["action_status"] = rec["sku"] print(f"[SYNC] {rec['object_id']} -> {rec['status']}") sync_state()你不需要手写这段代码。我的实际流程是:在 Antigravity 会话里描述需求:“写一个 Blender Python 脚本,读取指定路径的 wms_state.json,根据每个库位的 status 修改对应名称的货物占位物体材质,并给锚点写入自定义属性;找不到对象要打印警告但不能中断。”Agent 会把脚本生成好,然后我提醒它“通过 Blender MCP 执行这个脚本”。背后执行的本质,是 MCP 的一个执行脚本工具。
4.3 观察一次实时联动效果
脚本跑通之后,效果是立竿见影的。我们把模拟数据里shelf_A_01_L1的 status 从empty改成occupied,几秒后切到 Blender 视口,那个库位上的占位物体从半透明白色变成了红色,同时对象的属性面板里多了一个action_status = SKU-10086。
这种联动效果,如果放在传统流程里,需要先在 Blender 里建立一套材质切换机制、写一套 socket 接收逻辑、再做数据解析,没有一两天搞不完。现在变成了 Antigravity 的 Agent 生成代码,MCP 负责执行,相当于把“数据到场景”的桥自动化搭起来了。
不过光靠一次手动执行还不够。真正的数字孪生要求持续同步。所以我们又让 Agent 写了一个循环版本,思路是:while循环里每 5 秒sync_state()一次,同时监听停止标志。这种长时间运行的脚本如果卡死,就杀掉 Blender 端的任务再重跑,比在一个脚本里堆大量 Buffer 机制稳健。
4.4 让场景动起来:AGV 路径动画
数据颜色同步做完了,场景还差点意思——AGV 都趴着不动。为了让数字孪生展示更有说服力,我们给 AGV 加了简单路径动画。
做法也不复杂:在 Blender 里先建立一个路径曲线对象,代表 AGV 从库位 A 到月台的行驶路线;然后把 AGV 绑定到路径上,用关键帧控制路径偏移量。Antigravity 的提示词我写的是:
“生成一条从 shelf_A_03 位置到出库月台的贝塞尔曲线路径,让 agv_01 在这条路径上从起点移动到终点,时长 8 秒,并记录关键帧。”
执行完,在时序编辑器里拖一下时间轴,就能看到那台 AGV 沿着曲线缓缓驶向月台,库位颜色在它驶出后切换成绿色。虽然距离那种商业级的物理引擎动画还有距离,但作为概念验证和业务推演已经足够。
5. 常见问题与排查技巧实录
5.1 Antigravity 账号资格问题
这个问题在我们群里被问的概率非常高,症状很一致:注册后在弹窗里看到 “eligibility check failed” 或 “sorry, this account is ineligible to use antigravity”,无法进入工作区。
针对这个,老实说没有“技术性解法”,也不该有。正常情况下遵循官方渠道确认服务适用范围和账号资格就好。我们团队成员里确实有人注册后就顺利通过,有人等了一周才被放开,这属于服务侧的审核节奏。如果你已经走完正常注册流程还是被拒,建议检查注册邮箱是否常用、用户信息是否完整,然后通过官网帮助渠道反馈。
5.2 MCP 连接失败 / Agent 执行报错
另一个高频问题是:Antigravity 里 agent 跑着跑着提示 “Agent execution terminated due to error”,或者直接说连不上 Blender。我遇到的 80% 情况是下面三个原因之一:
- Blender 插件服务没有启动:Blender 必须保持打开,并且 N 面板里 MCP 服务开关是开启状态。
- 端口不一致:server 端监听的是 7777,Blender 插件设置的却是 8000。两边对不上,连接自然失败。
- Blender 界面被锁住:Agent 调用大量建模命令时,Blender 界面如果弹出了模态对话框(比如文件保存框),命令会被阻塞。我在跑自动建模脚本之前一定先确认 Blender 界面干净、没有弹窗。
排查办法:先把 Blender 的 MCP 插件连接状态打出来(面板上有日志),再在 Antigravity 侧发一个最简单的指令“读取当前 Blender 场景对象列表”,如果这步能通,说明链路没断。链路通了还报错,再把 agent 会话里的详细报错直接粘贴给 Agent 让它自查。
5.3 对象命名不一致导致的同步失败
数字孪生数据映射跑不起来,最隐蔽的原因是命名有一处不一致。我们真实的踩坑案例是:Blender 场景里货架对象名是shelf_A_01_L1,但数据文件里写成了shelf_A_01_l1(大小写差异)。Blender 命名是分大小写的,bpy.data.objects.get() 找不到对象,打印一条警告后继续执行,看起来“没报错”,但实际这个库位的颜色永远不变。
这个问题治本的办法有两个:一是从一开始就定死命名规范,全部用小写+下划线,不搞驼峰;二是在同步脚本末尾加一个统计输出,比如“本次同步 40 条,成功 39 条,失败 1 条”,失败记录里带上 object_id,一眼就能发现问题。
5.4 场景卡顿与性能优化
一个 5 排 8 库位的双面货架场景,其实对象数量已经超过 400 个。如果我建模型时把每个货物占位都做成高面数立方体,场景会明显卡顿。优化手段我总结为三件套:
- 实例化:用 Blender 的 Collection Instance,让同类型的货物占位共用一份几何数据,而不是各生成一份独立的网格。
- 减面:建模时把网格细分数压低,库位占位物体用 Cube 而不是 UV Sphere,默认场景不需要高精细曲面。
- 视口显示轻量化:在 Blender 的视口显示里把阴影和质量等级调低,数字孪生开发阶段不需要最高画质,预览看状态才重要。
5.5 常见问题速查
我把上面这些经验整理成一张表,方便你在现场按症状查表处理。
| 症状 | 可能原因 | 处理动作 |
|---|---|---|
| Antigravity 提示账号不可用 | 账号资格未通过 / 注册信息不完整 | 走官方审核渠道确认服务范围,确保注册信息真实统一 |
| Agent 说连接不到 Blender | Blender 插件未启动 / 端口不一致 | 检查 N 面板连接状态,核对端口配置 |
| 脚本执行中 Blender 卡住 | 弹窗阻塞 / 命令过多 | 关闭弹窗,拆分批量命令,分批执行 |
| 数据颜色不同步 | 对象名不一致 / 材质名未匹配 | 打印同步失败日志,检查命名与数据结构 |
| 场景拖动卡顿 | 模型面数过高 | 开启实例化,降视口质量 |
| 材质不生效 | 材质未设为活动材质 | 用 holder.active_material 指向对应材质对象 |
这套流程跑下来,我最大的感受是:“AI 建模”并不是让人彻底不干活,而是把原来需要大量手工执行的重复劳动压缩成了对话。场景规划、命名规范、数据结构设计,这些决定数字孪生质量的底层工作,还是要人来做;但一旦你把规则想清楚,Antigravity 和 Blender MCP 会把这些规则执行得非常到位。
我们在项目里也是先把基础仓储场景和同步脚本跑通,才敢规划下篇那些更复杂的东西:像在 Blender 里做 3D 仓库分区热力图、对接真实 WMS 接口、再把场景发布成浏览器里能访问的 Web 数字孪生页面。下篇的坑估计不会少,但至少这条技术路径已经证明是走得通的。你先按这篇文章把场景和状态同步搭起来,体验一下“说几句话,仓库就在 Blender 里长出来”的感觉,后面的事情会顺很多。