⭐ Unity 编辑器扩展:简单自动合并多个 Mesh 并导出为 .asset
🎮效果如下:
🧩 工具功能概览
✅ 支持将一个 GameObject 下所有子物体的网格按材质分组合并
✅ 可选择是否将合并后的 Mesh 导出为资源文件 .asset
✅ 一键操作,无需编写运行时代码
✅ 自动处理世界坐标转换与 UV 信息
📦 实现原理概述
Unity 提供了 Mesh.CombineMeshes()
方法来实现多个网格的合并,我们通过 MeshFilter
获取所有需要合并的网格数据,并用材质进行分组,再生成新的合并网格赋值到新 GameObject 中。
此外,我们利用 AssetDatabase.CreateAsset()
将合并结果导出为 Unity 资源文件,方便后续使用和打包优化。
🧱 完整代码(含注释)
以下是完整的编辑器脚本,直接复制粘贴到 Editor
文件夹下即可使用:
using System.Collections.Generic;using System.IO;using UnityEditor;using UnityEngine;namespace UniMeshCombiner{ // 自定义编辑器窗口类,继承自 UnityEditor.EditorWindow public class UniMeshCombinerWindow : EditorWindow { // 导出的目标目录(Project 视图中一个文件夹) private DefaultAsset _exportDirectory = null; // 要合并网格的目标 GameObject(包含 MeshFilter 的物体) private GameObject _combineTarget = null; // 是否导出合并后的 Mesh 为 .asset 文件 private bool _exportMesh; // 在 Unity 菜单栏添加一个窗口菜单项 [MenuItem(\"Window/UniMeshCombiner\")] static void Open() { // 创建并显示窗口,标题为 \"UniMeshCombiner\" GetWindow(\"UniMeshCombiner\").Show(); } // 编辑器窗口 GUI 绘制函数 void OnGUI() { // 拖入或选择要合并网格的目标物体 _combineTarget = (GameObject)EditorGUILayout.ObjectField(\"CombineTarget\", _combineTarget, typeof(GameObject), true); // 选择是否导出合并结果为资源文件 _exportMesh = EditorGUILayout.Toggle(\"Export Mesh\", _exportMesh); // 拖入导出目录,类型为 DefaultAsset(文件夹) _exportDirectory = (DefaultAsset)EditorGUILayout.ObjectField(\"Export Directory\", _exportDirectory, typeof(DefaultAsset), true); // 合并按钮 if (GUILayout.Button(\"Combine\")) { // 若未指定目标,则不执行 if (_combineTarget == null) { return; } // 调用合并函数 CombineMesh(); } } // 执行网格合并逻辑 void CombineMesh() { // 获取目标对象下所有子对象的 MeshFilter 组件 var meshFilters = _combineTarget.GetComponentsInChildren(); // 用字典记录每种材质对应的 CombineInstance 列表(分材质合并) var combineMeshInstanceDictionary = new Dictionary<Material, List>(); // 遍历所有 MeshFilter foreach (var meshFilter in meshFilters) { var mesh = meshFilter.sharedMesh; // 获取 mesh 数据 var vertices = new List(); mesh.GetVertices(vertices); // 获取顶点数据 var materials = meshFilter.GetComponent().sharedMaterials; // 获取材质数组 var subMeshCount = meshFilter.sharedMesh.subMeshCount; // 获取子网格数量 // 遍历每个子网格(按材质处理) for (var i = 0; i < subMeshCount; i++) { var material = materials[i]; // 当前子网格使用的材质 var triangles = new List(); mesh.GetTriangles(triangles, i); // 获取当前子网格的三角面索引 // 创建一个新 mesh,仅包含当前 submesh 的顶点和三角面 var newMesh = new Mesh { vertices = vertices.ToArray(), triangles = triangles.ToArray(), uv = mesh.uv, normals = mesh.normals }; // 若该材质尚未记录,则初始化列表 if (!combineMeshInstanceDictionary.ContainsKey(material)) { combineMeshInstanceDictionary.Add(material, new List()); } // 创建 CombineInstance 并加入字典 var combineInstance = new CombineInstance { transform = meshFilter.transform.localToWorldMatrix, // 记录世界坐标变换矩阵 mesh = newMesh }; combineMeshInstanceDictionary[material].Add(combineInstance); } } // 隐藏原始对象 _combineTarget.SetActive(false); // 遍历每种材质的合并实例列表 foreach (var kvp in combineMeshInstanceDictionary) { var material = kvp.Key; var combineList = kvp.Value; // 为该材质创建一个新的 GameObject(用于显示合并结果) var newObject = new GameObject(material.name); // 添加 MeshRenderer 和 MeshFilter 组件 var meshRenderer = newObject.AddComponent(); var meshFilter = newObject.AddComponent(); // 设置材质 meshRenderer.material = material; // 创建新 Mesh 并进行合并 var mesh = new Mesh(); mesh.CombineMeshes(combineList.ToArray()); // 自动生成第二套 UV(用于烘焙或光照贴图) Unwrapping.GenerateSecondaryUVSet(mesh); // 将合并后的 mesh 指定到 MeshFilter 上 meshFilter.sharedMesh = mesh; // 设置合并结果的父物体为原目标的父物体 newObject.transform.parent = _combineTarget.transform.parent; // 判断是否导出为 asset if (!_exportMesh || _exportDirectory == null) { continue; } // 执行导出 ExportMesh(mesh, material.name); } } // 导出 mesh 为 .asset 文件 void ExportMesh(Mesh mesh, string fileName) { // 获取文件夹在项目中的路径 var exportDirectoryPath = AssetDatabase.GetAssetPath(_exportDirectory); // 确保文件名后缀为 .asset if (Path.GetExtension(fileName) != \".asset\") { fileName += \".asset\"; } // 拼接完整导出路径 var exportPath = Path.Combine(exportDirectoryPath, fileName); // 创建资源文件 AssetDatabase.CreateAsset(mesh, exportPath); } }}
🧪 使用方法
-
在
Assets
目录下创建Editor
文件夹,将上述代码保存为UniMeshCombinerWindow.cs
; -
打开 Unity,菜单栏点击:
Window > UniMeshCombiner
; -
拖入你想合并的父物体到
CombineTarget
; -
勾选
Export Mesh
可将结果保存为.asset
文件; -
选择导出目录;
-
点击
Combine
即可完成合并!感谢大家的观看,您的点赞和关注是我最大的动力
不定时更新知识点和干货呦~