做数字孪生项目,最容易被低估的一步,不是三维建模,不是驱动动画,也不是 PLC 通信,而是把客户的 CAD 数据“弄进”开发平台。尤其是遇到大型装配体,几十个 G 的 STEP、CATPart、SolidWorks 文件,直接拖进 Unity 的结果往往是崩溃、破面、比例错乱、材质全黑,接着就是开发人员拿着原始模型在软件之间来回倒腾,几天时间就这么耗掉了。
realvirtual 是一个基于 Unity 的工业数字孪生开发平台,它的视频系列教程第 6 期把焦点放在了“如何自动将大型的 CAD 数据导入到数字孪生开发平台中”。这个选题非常精准,因为很多 Unity 数字孪生项目并不是死于技术难度,而是死于资产导入环节的低效。本文会结合这一期的主题,把大型 CAD 自动导入的思路、流程、脚本示例和坑位完整拆开,帮你建立一条可持续复用的 CAD 到 Unity 数字孪生的资产管线。
先说结论:自动导入不是找一个“一键转换工具”那么冲动,本质上它是一次数据治理。我们需要先把 CAD 数据整理成统一的中间格式,再用脚本批量转换和导入,最后在 Unity 内部做场景化优化。这篇文章会围绕真实项目里最常遇到的场景展开,你可以直接拿流程和代码去改。
1. 这篇文章真正要解决的问题
如果你只做一个小方块或一台设备的演示,手动导入 CAD 完全没问题。但真正的工业数字孪生项目,面对的往往是整条产线、整个车间、甚至一整座工厂。我见过的最典型场景是:甲方交付了 60 多个装配体,每个装配体里又有上百个零件,原始模型可能来自 SolidWorks、NX、Creo、CATIA 和 AutoCAD,格式有 sldprt、stp、igs、dwg、sat。这时候手动导入根本不可行。
真正要解决的是三个问题。
第一,数据格式不统一。不同 CAD 软件导出的文件格式差异巨大,Unity 原生不支持绝大多数 CAD 格式,必须找到一个稳定可靠的中转方案。第二,单位、坐标系、命名混乱。有的模型用毫米、有的用英寸,有的原点在世界坐标中心的几公里外,如果导入时不统一,后面所有定位和对齐工作都会作废。第三,模型结构过重。CAD 装配体包含大量倒角、螺纹、隐藏零件,直接导入会让 Unity 场景卡成幻灯片。
realvirtual 视频系列教程第 6 期正是在这个背景下展开的。它要解决的,不是某一个文件的导入问题,而是一条批量、自动、可重复的 CAD 到数字孪生平台的导入管线。从工程视角看,这条管线比任何一个“点工具”都重要。
2. realvirtual 与 CAD 导入的数字孪生开发基础
2.1 什么是 realvirtual
realvirtual 是一套基于 Unity 的工业数字孪生与虚拟调试开发平台。它的核心价值在于把 Unity 这个通用游戏引擎,扩展成工业自动化场景下的数字孪生开发环境。你可以在 realvirtual 上搭建虚拟产线、接入 PLC 信号、模拟传感器和执行器、做虚拟调试,也可以用于操作员培训和工厂可视化。
在数字孪生开发中,三维模型是载体,逻辑和行为才是灵魂。realvirtual 提供了大量工业逻辑组件,比如传送带、机器人、传感器、AGV 等,但这些组件都需要绑定到实际的三维模型上。CAD 数据的导入质量,直接决定了这些逻辑组件能否正确工作。这也是为什么 realvirtual 官方教程会专门花一期来讲大型 CAD 自动导入。
2.2 CAD 数据在数字孪生体构建中的角色
数字孪生体构建有一个常见误区:以为把 CAD 模型导入 Unity,就是数字孪生了。其实 CAD 模型只是几何表达,它本身没有尺寸之外的语义信息。真正有价值的数字孪生体,需要把几何模型、运动学关系、传感器点位、控制接口和业务数据映射到一起。
从 CAD 导入开始,我们就要为后续的语义映射做准备。比如每个零件导入后叫什么名字,应该归到哪个父节点,原点在哪,轴的方向是什么。这些看似枯燥的规则,反而是数字孪生体构建中最重要的数据映射基础。如果你的模型导入后名字是Body1、Part3-1,那么后续做物料绑定、设备关联时,谁都分不清谁是谁。
2.3 为什么大型 CAD 数据不适合直接拖拽导入
很多新手第一次接触 Unity 数字孪生时,会尝试把原生的.sldprt或.step文件直接拖到 Unity 中。这个操作通常会失败,因为 Unity 自身的模型导入插件覆盖的是 FBX、OBJ、glTF 这类通用格式,对 CAD 原生格式支持有限。
即使你事先导出了 FBX,把大型装配体直接丢进 Unity 也不会好到哪里去。CAD 模型的精细度是面向制造的,而 Unity 场景是面向实时渲染的。一个包含 500 万个三角面的阀门模型,在 CAD 软件里很常见,但到了 Unity 中,即使高端显卡也会明显掉帧。
所以,自动导入不仅仅是“换一种方式导入”,它必须包含模型轻量化、网格修复、材质映射和场景组织这几个步骤。这些内容是 realvirtual 这类数字孪生平台落地的关键,也是本文后半部分要展开的实操重点。
3. 环境准备与前置条件
在开始搭建自动导入管线之前,先把需要用到的软件环境梳理清楚。由于很多人使用的是 Windows 开发环境,下面的准备以 Windows + Unity 为主,但脚本思路在 Linux 和 macOS 上同样适用。
3.1 软件清单
你需要准备以下基础工具:
| 工具 | 作用 | 说明 |
|---|---|---|
| Unity | 数字孪生运行环境 | 建议使用 LTS 版本,版本以你安装的 realvirtual 兼容版本为准 |
| realvirtual | 数字孪生开发平台 | 基于 Unity,提供工业逻辑组件和导入扩展 |
| CAD 原始软件 | 数据源 | SolidWorks、NX、Creo、CATIA 等,用于导出中性格式 |
| FreeCAD | 批量格式转换 | 开源免费,支持 STEP/IGES/STL 等格式处理 |
| Blender | 网格轻量化与转格式 | 开源免费,可以将 STL/OBJ/FBX 转换为 Unity 更友好的 FBX/glTF |
| Python | 批量脚本编排 | 用于遍历目录、调用外部工具、组织文件 |
| 文本编辑器 | 写脚本 | VS Code 或任意你习惯的编辑器 |
这里强调一点:版本号不要照抄任何教程,因为 realvirtual 和 Unity 的版本兼容性在不同时期差异很大。最稳妥的做法是先安装 Unity 的 LTS 版本,再根据 realvirtual 官方文档要求选择对应版本。本文重点演示的是通用思路,不绑定具体版本。
3.2 CAD 数据准备
在导入前,需要和客户或机械工程师约定好 CAD 数据的交付规范。没有规范的话,自动脚本再强大也会被混乱的源数据打败。
建议至少约定以下几点:
- 所有零件和装配体必须有清晰的命名,不要出现
Part1.SLDPRT这种无意义名称。 - 统一使用毫米作为单位。
- 模型放在与真实世界一致的坐标系位置,最好以一个固定参考点为原点。
- 复杂装配体中的标准件、隐藏件、装饰件,尽可能在 CAD 软件中提前清理。
这些约定不是审核别人的工作,而是减少后续 80% 的导入异常。实际项目中,我经常看到团队把时间花在“调整导入后的偏移”上,根源就是源数据坐标系不一致。
4. 核心流程拆解:从 CAD 到数字孪生
自动导入要有清晰的流程,每一步做什么、为什么做、不做会怎样,都要明确。下面是我推荐的七步流程。
4.1 第一步:数据清洗与资产盘点
在批量转换前,先把所有 CAD 文件集中到一个目录,用 Python 脚本扫描一遍,统计格式、文件大小、数量。这个步骤能帮你发现异常文件,比如空文件、0 字节文件、命名带特殊符号的文件。
数据清洗的另一个重要任务是剔除不需要导入的模型。CAD 装配体里常见的气缸标准件、螺栓螺母、内部不可见零件,在数字孪生场景里都可以用简模或贴图替代。如果一个产线模型里有几百个螺栓,每个螺栓都按精细 CAD 模型导入,场景性能会直接崩溃。
这个阶段建议生成一份“待导入清单”,以 Excel 或 CSV 形式记录下来,后续步骤可以按这份清单批量处理。
4.2 第二步:统一单位、坐标系与格式
CAD 软件导出的格式五花八门,为了能统一处理,我建议把所有原生格式转换成 STEP(.stp)作为中间交换格式。STEP 是工业领域最通用的中性格式,FreeCAD 对它的解析能力比较好,也能保留装配体结构信息。
如果原始 CAD 软件可以直接导出 STEP,就尽量在软件里导出;如果不能,可以使用 FreeCAD 的图形界面批量打开再另存为 STEP。这一步的目的,是把所有源文件咬到一个统一的起点上。
单位统一非常关键。如果某个模型是英寸,某个是毫米,转换到 Unity 后会出现一个零件几十米大、另一个却小如芝麻的情况。最稳妥的办法是在 CAD 软件导出时就把单位设置好,或者在 FreeCAD 中批量修正后再进入下一个流程。
4.3 第三步:批量转换与轻量化
这一步是整个自动化管线的核心。把 STEP 转换成 Unity 可用的中间格式,常见选择有两种:STL 和 OBJ。
STL 只包含三角网格信息,优点是通用、稳定,缺点是没有材质和颜色信息;OBJ 可以附带简单的材质信息,但在处理大型装配体时不如 STL 稳定。我的建议是,如果后续要做 PBR 材质精细展示,优先用 FBX 或 glTF;如果只做结构示意和逻辑仿真,STL 完全够用,而且转换最快。
转换不是一次性的。大型模型在转换后很可能还是太重,需要用 Blender 或 MeshLab 做减面(Decimate)。减面要注意度:设备模型保留 5 万到 10 万个三角面通常足够,传送带这类结构可更简化,机器人本体则需要保留关键结构特征。
4.4 第四步:批量导入 Unity 资源目录
转换后的 FBX 或 OBJ 文件,需要放到 Unity 项目的Assets目录下。这个步骤不建议手动复制,而是用目录结构预先规划,让脚本把文件复制到固定路径,然后在 Unity 中刷新资源。
推荐的目录结构是:
Assets/ ImportedCAD/ Line1/ MachineA/ MachineA.fbx MachineA_Materials/ Line2/ MachineB/ MachineB.fbx有了固定的目录结构,后续的批量导入脚本才能自动化。如果你用 Unity 的 Addressables 或 AssetBundle,目录结构也决定了加载和更新策略,所以从一开始就要规划好。
4.5 第五步:材质映射与物理属性设置
CAD 模型本身材质在转换过程中很容易丢失。解决方法是建立一张材质映射表,把 CAD 源文件里的材质名称对应到 Unity 中的标准材质。例如Steel对应金属感 PBR 材质,Aluminum对应拉丝铝材质,Rubber对应粗糙橡胶材质。
映射表的本质是规则。你可以用 CSV 文件维护,然后通过 Unity Editor 脚本读取。自动导入脚本植入时,按照映射表自动为每个网格分配材质。这样即使一次导入几百个零件,也不会出现导入后全部是灰色的状况。
物理属性也很重要。数字孪生平台中的碰撞体、刚体、关节都需要正确的物理参数。CAD 几何转换来的网格默认没有碰撞体,Unity 会在运行时自动生成网格碰撞体,但那样性能很差。更好的做法是在导入阶段批量给静态设备添加简化的 Box Collider 或 Mesh Collider。
4.6 第六步:场景组织与层级优化
导入 Unity 后不要直接把所有资源丢进场景。每个设备模型都应该挂在独立的 Prefab 下,并按照产线逻辑组织层级。比如:
Factory/ Line1/ MachineA/ Body Animation Sensors Conveyor/ Line2/ MachineB/层级组织的好处,是后续绑定 realvirtual 的逻辑组件时非常方便。实际项目中,传感器触发点、机器人的工具中心点、传送带的路径点,都需要有明确的挂载节点。如果你的模型层级混乱,后面做虚拟调试时又要重新建模。
4.7 第七步:验证与回滚
导入管线的最后一步是验证。打开 Unity 场景,检查模型比例、方向、位置,并记录场景的 FPS、三角面数量、材质数量。如果异常,需要能够快速定位是哪一步出的问题,并且可以回退到上一步,而不是手动修改上百个模型。
回滚机制可以通过 Git 对脚本和资源目录做版本控制。CAD 原始文件通常很大,不建议直接纳入 Git,但转换脚本、映射表、Unity 场景文件和项目设置一定要纳入版本管理。这样每次改动管线,都可以知道影响范围。
5. 自动导入脚本示例
下面给出几个可以直接拿去改的脚本。代码的目的是演示思路,具体路径、格式、API 需要根据你的项目环境调整。
5.1 用 Python 扫描 CAD 文件并生成清单
你需要先写出“数据清洗”阶段的第一步:遍历所有文件,统计格式和大小,并输出 CSV 清单。这个脚本在任何 Python 环境都能运行。
# 文件路径:tools/scan_cad_files.py import os import csv from collections import Counter SOURCE_DIR = r"D:\Projects\_source_cad" OUTPUT_CSV = r"D:\Projects\_source_cad\cad_file_list.csv" SUPPORTED_EXT = {".stp", ".step", ".igs", ".iges", ".sldprt", ".sldasm", ".prt", ".asm", ".dwg", ".dxf", ".sat"} def main(): if not os.path.exists(SOURCE_DIR): print(f"目录不存在: {SOURCE_DIR}") return rows = [] ext_counter = Counter() for root, _, files in os.walk(SOURCE_DIR): for name in files: ext = os.path.splitext(name)[1].lower() if ext not in SUPPORTED_EXT: continue full_path = os.path.join(root, name) size_mb = os.path.getsize(full_path) / 1024 / 1024 rows.append([full_path, ext, f"{size_mb:.2f}MB"]) ext_counter[ext] += 1 with open(OUTPUT_CSV, "w", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) writer.writerow(["path", "extension", "size"]) writer.writerows(rows) print(f"扫描完成,共 {len(rows)} 个文件") for ext, count in ext_counter.items(): print(f" {ext}: {count} 个") if __name__ == "__main__": main()这个脚本解决的是“我到底有哪些 CAD 文件”的问题。运行后会输出 CSV 清单,你可以在 Excel 中筛选出不需要导入的零件,甚至可以再追加清理规则。
5.2 使用 FreeCAD 批量将 STEP 转为 STL
转换到 STL 是最稳定的一条路径。FreeCAD 支持通过命令行执行 Python 脚本。下面这个脚本会遍历指定目录中的所有.stp和.step文件,并转换成同名.stl文件。
# 文件路径:tools/step_to_stl.py import os import sys INPUT_DIR = r"D:\Projects\_converted_step" OUTPUT_DIR = r"D:\Projects\_converted_stl" STEP_EXTS = (".stp", ".step") # 这个脚本由 FreeCAD 的 Python 解释器执行 import FreeCAD as App import Part def convert_file(step_path, stl_path): # 读取 STEP 文件中的几何形状 shape = Part.Shape() shape.read(step_path) # 导出为 STL,默认使用线性偏转控制网格精度 shape.exportStl(stl_path) print(f"转换完成: {step_path} -> {stl_path}") def main(): if not os.path.exists(INPUT_DIR): print(f"输入目录不存在: {INPUT_DIR}") sys.exit(1) os.makedirs(OUTPUT_DIR, exist_ok=True) for root, _, files in os.walk(INPUT_DIR): for file in files: if not file.lower().endswith(STEP_EXTS): continue rel_path = os.path.relpath(os.path.join(root, file), INPUT_DIR) stl_path = os.path.join(OUTPUT_DIR, os.path.splitext(rel_path)[0] + ".stl") os.makedirs(os.path.dirname(stl_path), exist_ok=True) convert_file(os.path.join(root, file), stl_path) if __name__ == "__main__": main()注意:这个脚本必须在 FreeCAD 提供的 Python 环境中运行,而不是普通系统 Python。你可以通过 FreeCAD 的快捷方式在命令行执行:
freecadcmd.exe step_to_stl.py如果你的 FreeCAD 版本不同,请把freecadcmd.exe替换为你本机命令。脚本中的网格精度参数没有写死,是因为不同项目对精度要求不同。精度越高,STL 文件越大,在 Unity 中越卡。实际使用时建议先在几个代表性模型上测试不同偏转值。
5.3 使用 Blender 批量轻量化并导出 FBX
STL 文件没有颜色和材质,如果想在 Unity 中保留基础外观,建议用 Blender 做一次轻量化,再导出 FBX。Blender 支持命令行执行 Python 脚本,这是一个典型的批处理流程。
# 文件路径:tools/stl_to_fbx_batch.py import bpy import os STL_DIR = r"D:\Projects\_converted_stl" FBX_DIR = r"D:\Projects\_converted_fbx" def process_one(stl_path, fbx_path): # 清空当前场景 bpy.ops.wm.read_factory_settings(use_empty=True) # 导入 STL bpy.ops.wm.stl_import(filepath=stl_path) # 选中所有对象并合并到单一网格(可选) bpy.ops.object.select_all(action='SELECT') bpy.ops.object.join() # 简化为目标面数 bpy.ops.object.modifier_add(type='DECIMATE') bpy.context.object.modifiers["Decimate"].ratio = 0.5 # 导出 FBX os.makedirs(os.path.dirname(fbx_path), exist_ok=True) bpy.ops.export_scene.fbx(filepath=fbx_path, use_selection=False) print(f"导出FBX: {fbx_path}") def main(): os.makedirs(FBX_DIR, exist_ok=True) for root, _, files in os.walk(STL_DIR): for file in files: if file.lower().endswith(".stl"): stl_path = os.path.join(root, file) rel_path = os.path.relpath(stl_path, STL_DIR) fbx_path = os.path.join(FBX_DIR, os.path.splitext(rel_path)[0] + ".fbx") process_one(stl_path, fbx_path) if __name__ == "__main__": main()Blender 命令行运行方式:
blender --background --python stl_to_fbx_batch.py这里的ratio = 0.5表示保留 50% 的面,是一个示例值。真实项目中建议根据 Unity Profiler 的统计去调节,目标单个设备模型不超过 10 万三角面。
5.4 Unity 侧批量导入与资源设置
当 FBX 文件已经放进 Unity 项目的Assets/ImportedCAD目录后,可以在 Unity 中写一个 Editor 脚本,批量刷新导入设置。Unity 的AssetDatabase和ModelImporter是常用的资源管理 API。
// 文件路径:Assets/Editor/CADBatchImport.cs using System.IO; using UnityEditor; using UnityEngine; public static class CADBatchImport { [MenuItem("Tools/CAD Batch Import Settings")] public static void ApplyImportSettings() { string root = "Assets/ImportedCAD"; string[] files = Directory.GetFiles(root, "*.fbx", SearchOption.AllDirectories); int count = 0; foreach (string file in files) { string assetPath = file.Replace("\\", "/"); ModelImporter importer = AssetImporter.GetAtPath(assetPath) as ModelImporter; if (importer == null) { Debug.LogWarning($"跳过非模型文件: {assetPath}"); continue; } // 根据项目需求设置导入参数 importer.globalScale = 1f; importer.useFileScale = true; importer.isReadable = false; importer.optimizeGameObjects = true; importer.addCollider = false; // 重新导入使其生效 AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); count++; } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Debug.Log($"批量导入设置完成,共处理 {count} 个 FBX 文件"); } }脚本执行方式有两种:在 Unity 菜单栏点击Tools/CAD Batch Import Settings,或者使用 Unity 批处理模式:
Unity.exe -batchmode -quit -projectPath "D:\Projects\MyDigitalTwin" -executeMethod CADBatchImport.ApplyImportSettings这段代码确保每个 FBX 模型都以优化的方式导入:不保留可读网格以节省内存,不自动生成碰撞体,启用游戏物体优化以提升场景运行性能。如果你的 realvirtual 组件需要读取模型顶点数据,那就必须把isReadable设为true,具体情况要按项目需求来。
6. 运行结果与效果验证
脚本写完之后,如何判断“自动导入”是成功的?不能只看文件是否存在,需要从几个维度验证。
6.1 资源阶段验证
在资源阶段,你需要确认:
- 原始 100 个 CAD 文件中,有多少成功生成了 STL,多少成功生成了 FBX。
- 转换过程和日志里有没有出现失败的模型文件名。
- 最终 FBX 文件总大小相比源 STEP 文件减小了多少。
如果某个模型转换失败,首先要看源文件是否损坏,再看格式是否特殊。FreeCAD 对某些复杂曲面模型的处理能力可能有限,这时可以考虑这类模型单独用原始 CAD 软件导出。
6.2 Unity 场景阶段验证
打开 Unity 后,把批量导入的 Prefab 一个一个拖到场景中,先不急着布置位置,先检查:
- 模型是否有缩放异常。真实设备长度如果是 2 米,在 Unity 场景中应该接近 2 个单位。
- 模型朝向是否正常。很多 CAD 软件的 Z 轴朝上,而 Unity 也是 Z 朝上,但有些软件是 Y 轴朝上,这就需要在 Blender 或 CAD 软件中旋转后再导出。
- 模型是否出现黑面、透明面、破洞。这种情况通常是法线方向翻转,需要在 Blender 中统一法线。
验证不只在编辑器里看。运行数字孪生场景,打开 Unity Profiler,观察 Draw Call 数量、三角面总数和帧率。一个大型车间场景,目标帧率至少要达到 30 FPS 以上,建议 60 FPS。如果发现某台设备的网格面数过高,就用 Blender 脚本单独再减一次面。
6.3 逻辑联动验证
realvirtual 平台中,CAD 导入不只是为了好看,还要和逻辑联动。你需要测试:设备触点是否与模型表面重合,传送带路径是否贴着模型表面,机器人工具中心点是否落在正确位置。如果位置偏移很大,很可能是导入时坐标系设置不对。
这一步验证如果发现问题,不要用手动拖拽模型去挪。正确做法是回到预处理阶段,修正源文件的坐标系,再重新走一遍导入流程。只有这样,当项目需要更新模型时,才不会再次偏移。
7. 常见问题与排查思路
在实际操作中,CAD 自动导入会遇到各种各样的问题。下面整理了一张排查表,你可以按表里的思路逐步定位。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 导入后模型比例不对 | 单位不一致或导入设置缩放错误 | 对比源模型尺寸与 Unity 中尺寸 | 统一毫米单位,检查globalScale和useFileScale |
| 模型在场景中位置偏移巨大 | CAD 原始坐标系与 Unity 不一致 | 检查源文件原点位置 | 在 CAD 或 Blender 中统一模型原点,再重新导出 |
| 模型表面出现黑面或透明 | 法线方向反转 | 在 Blender 中开启面朝向显示 | 使用bpy.ops.mesh.normals_make_consistent统一法线 |
| 模型导入后全是灰色材质 | 中间格式丢失材质信息 | 检查 FBX 导入材质设置 | 建立材质映射表,用 Unity Editor 脚本自动指定 |
| 场景帧率明显下降 | 三角面数过多或 Draw Call 过高 | 用 Unity Profiler 查看瓶颈 | 用 Blender 减面,使用 LOD,合并静态网格 |
| 自动脚本转换部分文件失败 | 源文件格式特殊或损坏 | 查看 FreeCAD 输出日志 | 用原始 CAD 软件转换后再处理,或单独修复模型 |
| realvirtual 组件绑定后位置不对 | 模型层级与组件挂载点不一致 | 检查 Prefab 子节点层级 | 在导入阶段规划好组件挂载节点,避免运行时改名 |
| 模型可以显示但无法碰撞 | 未生成碰撞体或使用网格碰撞体过多 | 检查 Collider 组件 | 用简单碰撞体替代 Mesh Collider |
这里特别要提醒的是:千万不要在生产环境中临时手动修改数百个模型。你看到的问题只是其中一个,手动修改只能解决一个,后续更新模型时问题还会回来。一切修改都要走脚本,这样才是可持续的自动导入管线。
8. 大型 CAD 导入的最佳实践与工程建议
8.1 建立命名规范是自动化的前提
自动导入脚本能跑通的前提,是源文件命名可以预测。我建议团队内部统一一个命名模板:
设备类型_产线编号_序号_名称例如Robot_L1_001_Arm、Conveyor_L2_002_Belt。导入脚本可以根据前缀自动分类,后续在 Unity 中生成 Prefab 也会很有规律。如果客户的原始文件命名混乱,至少要在转换脚本里加入重命名规则,避免 Unity 中出现大量重名或中文名的问题。
8.2 不要让 CAD 源数据直接成为运行时资产
CAD 原始文件应该和数字孪生项目分开管理。原始文件是甲方交付物,大小动辄几十 GB;Unity 项目里只放转换后的轻量化模型和脚本。这个隔离可以避免版本管理混乱,也方便在项目迭代时重新转换。
建议目录结构如下:
D:\Projects\DigitalTwin\ _source_cad\ # 原始 CAD,按客户分目录 _converted_step\ # 中间 STEP 文件 _converted_stl\ # 轻量化 STL _converted_fbx\ # 最终 FBX,进入 Unity 项目 UnityProject\Assets\ImportedCAD\ # Unity 资源每一层都独立存在,上一层的输出就是下一层的输入。当源数据更新时,只需要从第一步重新执行,之后所有步骤可以自动跑完。
8.3 批量导入后必须做 LOD 与遮挡剔除
大型数字孪生场景不是静态摆设,而是可以漫游和交互的。如果所有模型全精度显示,性能压力很大。Unity 自带的 LOD Group 可以根据摄像机距离切换高模和低模,建议在导入脚本里批量生成 LOD 0、LOD 1、LOD 2 三个等级。
遮挡剔除(Occlusion Culling)也建议开启。车间场景里,摄像机看不到的房间和设备不应该渲染。在 Unity 中先烘焙遮挡数据,再进行实时渲染,能明显提升帧率。
8.4 使用版本管理保护自动化脚本
自动导入管线本身就是一项资产。STEP 转换脚本、Blender 脚本、Unity Editor 脚本、材质映射表,都应该纳入 Git 或 SVN 管理。这样当某个批次导入效果不理想时,你可以快速回退到上一版本,找到是哪次脚本改动引起的。
更重要的是,脚本要写注释。不要写“这个命令用途是什么”这种废话,而是写“为什么要在这里做减面、为什么这个模型不能开 Mesh Collider”。团队协作时,这些注释能省下大量沟通成本。
8.5 建立导入效果验收清单
我建议每个数字孪生项目都维护一份验收清单,比如:
- 所有设备模型命名符合规范。
- 所有模型单位统一为毫米。
- 所有模型原点位置正确,没有异常偏移。
- 所有模型网格面数在目标范围内。
- 所有模型材质已按映射表加载,不是默认灰色材质。
- 场景运行帧率达到项目要求。
- realvirtual 绑定测试通过,设备动作与模型位置一致。
这份清单应该放在项目文档根部,每次导入新批次后逐项打勾。它能帮团队从“感觉差不多”升级到“数据驱动判断”。
9. 总结与后续学习方向
CAD 自动导入数字孪生平台,表面上是一个技术操作问题,实际是一个数据工程问题。真正值得投入的,不是找一个“万能导入按钮”,而是建立一条从原始 CAD 到 Unity 资源的自动化管线。这条管线包含格式统一、网格轻量化、命名规范、材质映射、批量导入和验证闭环。realvirtual 视频系列教程第 6 期的主题,恰恰是这个工程问题的核心切面。
对于下一步学习,建议你先从一个小型装配体跑通整个流程,再扩展到整线模型。第一步可以在 Python 环境把文件清单扫描出来;第二步用 FreeCAD 转出几个 STL;第三步在 Unity 中写一个简单的导入设置脚本;最后再接入 realvirtual 的组件测试整个流程。每一步跑通后,再增加复杂度。
一个小提醒:如果你的项目已经在生产环境中使用了一版手动导入的模型,不要一次性全量切换自动管线,先选一条产线或一个工位试点。对比新旧流程的导入时间、场景帧率和模型表现,确认收益后再全面铺开。自动导入不是银弹,但它是一条值得在前期投入的路径。把它做好,后面每一个数字孪生项目都会轻松很多。