Skip to content

Instantly share code, notes, and snippets.

@Wolfos
Created June 15, 2024 13:26
Show Gist options
  • Save Wolfos/2996fe475ae546f3a75459c84b503e68 to your computer and use it in GitHub Desktop.
Save Wolfos/2996fe475ae546f3a75459c84b503e68 to your computer and use it in GitHub Desktop.
Static mesh combiner for Unity. Very basic. Ignores meshes that have multiple materials.
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Rendering;
public class MeshCombiner : MonoBehaviour
{
[SerializeField, HideInInspector] private MeshRenderer[] meshRenderers;
[SerializeField, HideInInspector] private List<GameObject> combinedObjects;
[Button("Combine meshes")]
public void CombineMeshes()
{
UndoCombine();
meshRenderers = GetComponentsInChildren<MeshRenderer>().Where(m => m.enabled && m.gameObject.activeInHierarchy && m.gameObject.isStatic).ToArray();
Dictionary<Material, List<MeshFilter>> filtersByMaterial = new();
foreach (var meshRenderer in meshRenderers)
{
if(meshRenderer.sharedMaterials.Length > 1) continue;
var material = meshRenderer.sharedMaterial;
if (filtersByMaterial.ContainsKey(material) == false)
{
filtersByMaterial.Add(material, new());
}
var list = filtersByMaterial[material];
list.Add(meshRenderer.GetComponent<MeshFilter>());
}
Matrix4x4 GetParentRelativeMatrix(Transform childObject, Transform parentObject)
{
return parentObject.worldToLocalMatrix * childObject.localToWorldMatrix;
}
foreach (var kvp in filtersByMaterial)
{
var material = kvp.Key;
var meshFilters = kvp.Value;
var combine = new CombineInstance[meshFilters.Count];
for (var i = 0; i < combine.Length; i++)
{
combine[i].mesh = meshFilters[i].sharedMesh;
combine[i].transform = GetParentRelativeMatrix(meshFilters[i].transform, transform);
meshFilters[i].GetComponent<MeshRenderer>().enabled = false;
}
var combinedMesh = new Mesh();
combinedMesh.indexFormat = IndexFormat.UInt32;
combinedMesh.CombineMeshes(combine);
var go = new GameObject(material.name);
go.transform.parent = transform;
go.transform.localPosition = Vector3.zero;
go.transform.localRotation = Quaternion.identity;
go.transform.localScale = Vector3.one;
go.AddComponent<MeshFilter>().sharedMesh = combinedMesh;
go.AddComponent<MeshRenderer>().material = material;
combinedObjects.Add(go);
}
}
[Button("Undo")]
public void UndoCombine()
{
if (meshRenderers == null) return;
foreach (var meshRenderer in meshRenderers)
{
meshRenderer.enabled = true;
}
foreach (var go in combinedObjects)
{
DestroyImmediate(go);
}
combinedObjects.Clear();
meshRenderers = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment