当前位置: 首页 > news >正文

⭐ 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);}}
}


🧪 使用方法

  1. Assets 目录下创建 Editor 文件夹,将上述代码保存为 UniMeshCombinerWindow.cs

  2. 打开 Unity,菜单栏点击:Window > UniMeshCombiner

  3. 拖入你想合并的父物体到 CombineTarget

  4. 勾选 Export Mesh 可将结果保存为 .asset 文件;

  5. 选择导出目录;

  6. 点击 Combine 即可完成合并!


    感谢大家的观看,您的点赞和关注是我最大的动力

    不定时更新知识点和干货呦~

http://www.dtcms.com/a/297337.html

相关文章:

  • 通过kettle获取API数据
  • 虚拟机docker elasticsearch启动失败
  • JMeter每次压测前清除全部以确保异常率准确(以黑马点评为例、详细图解)
  • 如何提高微信小程序的应用速度
  • 数据赋能(332)——安全与合规——保密管理
  • RocketMQ5.3.1的安装
  • C 语言数组深度解析:从内存布局到安全实践的全维度指南
  • 二开---01
  • 什么是FCR,如何提升FCR?
  • Springboot3.0 集成 RocketMQ5
  • linux配置ntp时间同步
  • 告别虚函数性能焦虑:深入剖析C++多态的现代设计模式
  • Go 官方 Elasticsearch 客户端 v9 快速上手与进阶实践*
  • 银河麒麟安装软件商店方法
  • 《设计模式之禅》笔记摘录 - 10.装饰模式
  • vue项目入门
  • PostgreSQL对象权限管理
  • 全新轻量化PHP网盘搜索引擎系统源码
  • 常用设计模式系列(十三)—组合模式
  • Oracle 的单体安装
  • Android Room 持久化库:简化数据库操作
  • Kingbasepostgis 安装实践
  • GaussDB 逻辑备份实操
  • AR眼镜重塑外科手术导航:精准“透视”新突破
  • Elasticsearch-8.17.0 centos7安装
  • 《Angular+Spring Boot:ERP前端采购销售库存协同架构解析》
  • AR与AI融合:医疗诊断的智能新引擎
  • 解决angular与jetty websocket 每30s自动断连的问题
  • 安装pyarrow包
  • 小程序安卓ApK转aab文件详情教程MacM4环境