⭐ 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.EditorWindowpublic 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<UniMeshCombinerWindow>("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<MeshFilter>();// 用字典记录每种材质对应的 CombineInstance 列表(分材质合并)var combineMeshInstanceDictionary = new Dictionary<Material, List<CombineInstance>>();// 遍历所有 MeshFilterforeach (var meshFilter in meshFilters){var mesh = meshFilter.sharedMesh; // 获取 mesh 数据var vertices = new List<Vector3>();mesh.GetVertices(vertices); // 获取顶点数据var materials = meshFilter.GetComponent<Renderer>().sharedMaterials; // 获取材质数组var subMeshCount = meshFilter.sharedMesh.subMeshCount; // 获取子网格数量// 遍历每个子网格(按材质处理)for (var i = 0; i < subMeshCount; i++){var material = materials[i]; // 当前子网格使用的材质var triangles = new List<int>();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>());}// 创建 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<MeshRenderer>();var meshFilter = newObject.AddComponent<MeshFilter>();// 设置材质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;// 判断是否导出为 assetif (!_exportMesh || _exportDirectory == null){continue;}// 执行导出ExportMesh(mesh, material.name);}}// 导出 mesh 为 .asset 文件void ExportMesh(Mesh mesh, string fileName){// 获取文件夹在项目中的路径var exportDirectoryPath = AssetDatabase.GetAssetPath(_exportDirectory);// 确保文件名后缀为 .assetif (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
即可完成合并!感谢大家的观看,您的点赞和关注是我最大的动力
不定时更新知识点和干货呦~