Last active
April 6, 2023 11:17
-
-
Save reveriejake/a80f131979017b23594d37ddc0671a04 to your computer and use it in GitHub Desktop.
More advanced mesh combiner that takes in a parent gameobject and combines all child meshes regardless of material count or triangle count. Outputs a lit of generated gameobjects that contain the combined meshe(s). Could probably use some optimizations ;). Modified and improved from https://www.youtube.com/watch?v=6APzUgckV7U&ab_channel=CraigPerko
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace PicoGames | |
{ | |
public class MeshCombiner | |
{ | |
const int MAX_VERT_COUNT = 65535; | |
public static GameObject[] Combine(GameObject obj) | |
{ | |
List<GameObject> renderGOs = new List<GameObject>(); | |
Queue<MeshFilter> filterQueue = new Queue<MeshFilter>(obj.GetComponentsInChildren<MeshFilter>()); | |
while (filterQueue.Count > 0) | |
{ | |
// Create New Render GO; | |
GameObject renderGO = new GameObject("RGO"); | |
renderGO.transform.SetParent(obj.transform); | |
renderGO.transform.position = Vector3.zero; | |
renderGO.hideFlags = HideFlags.DontSave; | |
var mr = renderGO.AddComponent<MeshRenderer>(); | |
var mf = renderGO.AddComponent<MeshFilter>(); | |
mf.mesh = GetMaxFilters(ref filterQueue, out var materials, false); | |
mr.sharedMaterials = materials.ToArray(); | |
renderGOs.Add(renderGO); | |
} | |
return renderGOs.ToArray(); | |
} | |
private static int GetVertexCount(Mesh mesh) | |
{ | |
int vertCount = 0; | |
for (int i = 0; i < mesh.subMeshCount; i++) | |
{ | |
vertCount += mesh.GetSubMesh(i).vertexCount; | |
} | |
return vertCount; | |
} | |
private static Mesh GetMaxFilters(ref Queue<MeshFilter> filterQueue, out List<Material> materials, bool setInactive) | |
{ | |
List<MeshFilter> filterList = new List<MeshFilter>(); | |
List<MeshRenderer> rendererList = new List<MeshRenderer>(); | |
int vertexCount = 0; | |
while (filterQueue.Count > 0) | |
{ | |
vertexCount += GetVertexCount(filterQueue.Peek().sharedMesh); | |
if (vertexCount > MAX_VERT_COUNT) | |
break; | |
var filter = filterQueue.Dequeue(); | |
filterList.Add(filter); | |
filter.gameObject.SetActive(!setInactive); | |
var renderer = filter.GetComponent<MeshRenderer>(); | |
if (renderer != null) | |
{ | |
rendererList.Add(renderer); | |
} | |
} | |
materials = new List<Material>(); | |
foreach (var renderer in rendererList) | |
{ | |
Material[] localMats = renderer.sharedMaterials; | |
foreach (var localMat in localMats) | |
{ | |
if (!materials.Contains(localMat)) | |
materials.Add(localMat); | |
} | |
} | |
List<Mesh> subMeshes = new List<Mesh>(); | |
foreach (Material material in materials) | |
{ | |
List<CombineInstance> combiners = new List<CombineInstance>(); | |
foreach (var filter in filterList) | |
{ | |
MeshRenderer renderer = filter.GetComponent<MeshRenderer>(); | |
if (renderer == null) | |
continue; | |
Material[] localMaterials = renderer.sharedMaterials; | |
for (int i = 0; i < localMaterials.Length; i++) | |
{ | |
if (localMaterials[i] != material) | |
continue; | |
CombineInstance ci = new CombineInstance(); | |
ci.mesh = filter.sharedMesh; | |
ci.subMeshIndex = i; | |
ci.transform = filter.transform.localToWorldMatrix; | |
combiners.Add(ci); | |
} | |
} | |
Mesh mesh = new Mesh(); | |
mesh.CombineMeshes(combiners.ToArray(), true); | |
subMeshes.Add(mesh); | |
} | |
List<CombineInstance> finalCombiners = new List<CombineInstance>(); | |
foreach (var mesh in subMeshes) | |
{ | |
CombineInstance ci = new CombineInstance(); | |
ci.mesh = mesh; | |
ci.subMeshIndex = 0; | |
ci.transform = Matrix4x4.identity; | |
finalCombiners.Add(ci); | |
} | |
Mesh finalMesh = new Mesh(); | |
finalMesh.CombineMeshes(finalCombiners.ToArray(), false); | |
return finalMesh; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment