Skip to content

Commit 7da698c

Browse files
authored
Create MeshCombineWizard.cs
1 parent deb18ac commit 7da698c

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// from https://forum.unity.com/threads/mesh-combine-wizard-free-unity-tool-source-code.444483/#post-5575042
2+
3+
using UnityEngine;
4+
using UnityEditor;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
8+
namespace UnityLibrary
9+
{
10+
public class MeshCombineWizard : ScriptableWizard
11+
{
12+
public GameObject parentOfObjectsToCombine;
13+
14+
[MenuItem("E.S. Tools/Mesh Combine Wizard")]
15+
static void CreateWizard()
16+
{
17+
ScriptableWizard.DisplayWizard<MeshCombineWizard>("Mesh Combine Wizard");
18+
}
19+
20+
void OnWizardCreate()
21+
{
22+
if (parentOfObjectsToCombine == null) return;
23+
24+
Vector3 originalPosition = parentOfObjectsToCombine.transform.position;
25+
parentOfObjectsToCombine.transform.position = Vector3.zero;
26+
27+
MeshFilter[] meshFilters = parentOfObjectsToCombine.GetComponentsInChildren<MeshFilter>();
28+
Dictionary<Material, List<MeshFilter>> materialToMeshFilterList = new Dictionary<Material, List<MeshFilter>>();
29+
List<GameObject> combinedObjects = new List<GameObject>();
30+
31+
for (int i = 0; i < meshFilters.Length; i++)
32+
{
33+
var materials = meshFilters[i].GetComponent<MeshRenderer>().sharedMaterials;
34+
if (materials == null) continue;
35+
if (materials.Length > 1)
36+
{
37+
parentOfObjectsToCombine.transform.position = originalPosition;
38+
Debug.LogError("Objects with multiple materials on the same mesh are not supported. Create multiple meshes from this object's sub-meshes in an external 3D tool and assign separate materials to each.");
39+
return;
40+
}
41+
var material = materials[0];
42+
if (materialToMeshFilterList.ContainsKey(material)) materialToMeshFilterList[material].Add(meshFilters[i]);
43+
else materialToMeshFilterList.Add(material, new List<MeshFilter>() { meshFilters[i] });
44+
}
45+
46+
47+
// NC 03/2020 changes the loop to create meshes smaller than 695536 vertices
48+
foreach (var entry in materialToMeshFilterList)
49+
{
50+
// get list of each meshes order by number of vertices
51+
List<MeshFilter> meshesWithSameMaterial = entry.Value.OrderByDescending(mf => mf.sharedMesh.vertexCount).ToList();
52+
// split into bins of 65536 vertices max
53+
int nrMeshes = meshesWithSameMaterial.Count;
54+
while (nrMeshes > 0)
55+
{
56+
string materialName = entry.Key.ToString().Split(' ')[0];
57+
List<MeshFilter> meshBin = new List<MeshFilter>();
58+
meshBin.Add(meshesWithSameMaterial[0]);
59+
meshesWithSameMaterial.RemoveAt(0);
60+
nrMeshes--;
61+
// add meshes in bin until 65536 vertices is reached
62+
for (int i = 0; i < meshesWithSameMaterial.Count; i++)
63+
{
64+
if (meshBin.Sum(mf => mf.sharedMesh.vertexCount) + meshesWithSameMaterial[i].sharedMesh.vertexCount < 65536)
65+
{
66+
meshBin.Add(meshesWithSameMaterial[i]);
67+
meshesWithSameMaterial.RemoveAt(i);
68+
i--;
69+
nrMeshes--;
70+
}
71+
}
72+
73+
// merge this bin
74+
CombineInstance[] combine = new CombineInstance[meshBin.Count];
75+
for (int i = 0; i < meshBin.Count; i++)
76+
{
77+
combine[i].mesh = meshBin[i].sharedMesh;
78+
combine[i].transform = meshBin[i].transform.localToWorldMatrix;
79+
}
80+
Mesh combinedMesh = new Mesh();
81+
combinedMesh.CombineMeshes(combine);
82+
83+
// save the mesh
84+
materialName += "_" + combinedMesh.GetInstanceID();
85+
if (meshBin.Count > 1)
86+
{
87+
AssetDatabase.CreateAsset(combinedMesh, "Assets/CombinedMeshes_" + materialName + ".asset"); ;
88+
}
89+
90+
// assign the mesh to a new go
91+
string goName = (materialToMeshFilterList.Count > 1) ? "CombinedMeshes_" + materialName : "CombinedMeshes_" + parentOfObjectsToCombine.name;
92+
GameObject combinedObject = new GameObject(goName);
93+
var filter = combinedObject.AddComponent<MeshFilter>();
94+
if (meshBin.Count > 1)
95+
{
96+
filter.sharedMesh = combinedMesh;
97+
}
98+
else
99+
{
100+
filter.sharedMesh = meshBin[0].sharedMesh; // the original mesh
101+
}
102+
var renderer = combinedObject.AddComponent<MeshRenderer>();
103+
renderer.sharedMaterial = entry.Key;
104+
combinedObjects.Add(combinedObject);
105+
}
106+
}
107+
108+
GameObject resultGO = null;
109+
if (combinedObjects.Count > 1)
110+
{
111+
resultGO = new GameObject("CombinedMeshes_" + parentOfObjectsToCombine.name);
112+
foreach (var combinedObject in combinedObjects) combinedObject.transform.parent = resultGO.transform;
113+
}
114+
else
115+
{
116+
resultGO = combinedObjects[0];
117+
}
118+
119+
Object prefab = PrefabUtility.CreateEmptyPrefab("Assets/" + resultGO.name + ".prefab");
120+
PrefabUtility.ReplacePrefab(resultGO, prefab, ReplacePrefabOptions.ConnectToPrefab);
121+
122+
parentOfObjectsToCombine.SetActive(false);
123+
parentOfObjectsToCombine.transform.position = originalPosition;
124+
resultGO.transform.position = originalPosition;
125+
}
126+
}
127+
}

0 commit comments

Comments
 (0)