|
/****************************************
|
|
Simple Mesh Combine
|
|
Copyright Unluck Software
|
|
www.chemicalbliss.com
|
|
*****************************************/
|
|
//Add script to the parent gameObject, then click combine
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
[AddComponentMenu("Simple Mesh Combine")]
|
|
|
|
public class SimpleMeshCombine : MonoBehaviour {
|
|
public GameObject[] combinedGameOjects; //Stores gameObjects that has been merged, mesh renderer disabled
|
|
public GameObject combined; //Stores the combined mesh gameObject
|
|
public string meshName = "Combined_Meshes"; //Asset name when saving as prefab
|
|
public bool _canGenerateLightmapUV;
|
|
public int vCount;
|
|
public bool generateLightmapUV;
|
|
public float lightmapScale = 1f;
|
|
|
|
public GameObject copyTarget;
|
|
public bool destroyOldColliders;
|
|
public bool keepStructure = true;
|
|
|
|
public Mesh autoOverwrite;
|
|
|
|
public bool setStatic = true;
|
|
|
|
public void EnableRenderers(bool e) {
|
|
for (int i = 0; i < combinedGameOjects.Length; i++) {
|
|
if (combinedGameOjects[i] == null) break;
|
|
Renderer renderer = combinedGameOjects[i].GetComponent<Renderer>();
|
|
if (renderer != null) renderer.enabled = e;
|
|
}
|
|
}
|
|
//Returns a meshFilter[] list of all renderer enabled meshfilters(so that it does not merge disabled meshes, useful when there are invisible box colliders)
|
|
public MeshFilter[] FindEnabledMeshes() {
|
|
MeshFilter[] renderers = null;
|
|
int count = 0;
|
|
renderers = transform.GetComponentsInChildren<MeshFilter>();
|
|
//count all the enabled meshrenderers in children
|
|
for (int i = 0; i < renderers.Length; i++) {
|
|
if ((renderers[i].GetComponent<MeshRenderer>() != null) && renderers[i].GetComponent<MeshRenderer>().enabled)
|
|
count++;
|
|
}
|
|
MeshFilter[] meshfilters = new MeshFilter[count];//creates a new array with the correct length
|
|
count = 0;
|
|
//adds all enabled meshes to the array
|
|
for (int ii = 0; ii < renderers.Length; ii++) {
|
|
if ((renderers[ii].GetComponent<MeshRenderer>() != null) && renderers[ii].GetComponent<MeshRenderer>().enabled) {
|
|
meshfilters[count] = renderers[ii];
|
|
count++;
|
|
}
|
|
}
|
|
return meshfilters;
|
|
}
|
|
|
|
|
|
public void CombineMeshes() {
|
|
GameObject combo = new GameObject();
|
|
combo.name = "_Combined Mesh [" + name + "]";
|
|
combo.gameObject.AddComponent<MeshFilter>();
|
|
combo.gameObject.AddComponent<MeshRenderer>();
|
|
MeshFilter[] meshFilters = null;
|
|
meshFilters = FindEnabledMeshes();
|
|
ArrayList materials = new ArrayList();
|
|
ArrayList combineInstanceArrays = new ArrayList();
|
|
combinedGameOjects = new GameObject[meshFilters.Length];
|
|
for (int i = 0; i < meshFilters.Length; i++) {
|
|
combinedGameOjects[i] = meshFilters[i].gameObject;
|
|
MeshRenderer meshRenderer = meshFilters[i].GetComponent<MeshRenderer>();
|
|
meshFilters[i].transform.gameObject.GetComponent<Renderer>().enabled = false;
|
|
if (meshFilters[i].sharedMesh == null) {
|
|
#if UNITY_EDITOR
|
|
Debug.LogWarning("SimpleMeshCombine : " + meshFilters[i].gameObject + " [Mesh Filter] has no [Mesh], mesh will not be included in combine..");
|
|
#endif
|
|
break;
|
|
}
|
|
for (int o = 0; o < meshFilters[i].sharedMesh.subMeshCount; o++) {
|
|
if (meshRenderer == null) {
|
|
#if UNITY_EDITOR
|
|
Debug.LogWarning("SimpleMeshCombine : " + meshFilters[i].gameObject + "has a [Mesh Filter] but no [Mesh Renderer], mesh will not be included in combine.");
|
|
#endif
|
|
break;
|
|
}
|
|
if (o < meshRenderer.sharedMaterials.Length && o < meshFilters[i].sharedMesh.subMeshCount) {
|
|
int materialArrayIndex = Contains(materials, meshRenderer.sharedMaterials[o]);
|
|
if (materialArrayIndex == -1) {
|
|
materials.Add(meshRenderer.sharedMaterials[o]);
|
|
materialArrayIndex = materials.Count - 1;
|
|
}
|
|
combineInstanceArrays.Add(new ArrayList());
|
|
CombineInstance combineInstance = new CombineInstance();
|
|
combineInstance.transform = meshRenderer.transform.localToWorldMatrix;
|
|
//Fix for Unity 2017 Bug
|
|
#if UNITY_2017
|
|
if (meshFilters[i].sharedMesh.subMeshCount > 1) combineInstance.mesh = SubMeshFix.GetSubmesh(meshFilters[i].sharedMesh,o);
|
|
else {
|
|
combineInstance.mesh = meshFilters[i].sharedMesh;
|
|
}
|
|
#else
|
|
combineInstance.mesh = meshFilters[i].sharedMesh;
|
|
combineInstance.subMeshIndex = o;
|
|
#endif
|
|
(combineInstanceArrays[materialArrayIndex] as ArrayList).Add(combineInstance);
|
|
}
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
else {
|
|
Debug.LogWarning("Simple Mesh Combine: GameObject [ " + meshRenderer.gameObject.name + " ] is missing a material (Mesh or sub-mesh ignored from combine)");
|
|
}
|
|
#endif
|
|
}
|
|
#if UNITY_EDITOR
|
|
EditorUtility.DisplayProgressBar("Combining", "", (float)i);
|
|
#endif
|
|
}
|
|
|
|
Mesh[] meshes = new Mesh[materials.Count];
|
|
CombineInstance[] combineInstances = new CombineInstance[materials.Count];
|
|
for (int m = 0; m < materials.Count; m++) {
|
|
CombineInstance[] combineInstanceArray = (combineInstanceArrays[m] as ArrayList).ToArray(typeof(CombineInstance)) as CombineInstance[];
|
|
meshes[m] = new Mesh();
|
|
meshes[m].CombineMeshes(combineInstanceArray, true, true);
|
|
combineInstances[m] = new CombineInstance();
|
|
combineInstances[m].mesh = meshes[m];
|
|
combineInstances[m].subMeshIndex = 0;
|
|
}
|
|
Mesh ms = combo.GetComponent<MeshFilter>().sharedMesh = new Mesh();
|
|
ms.Clear();
|
|
ms.CombineMeshes(combineInstances, false, false);
|
|
combo.GetComponent<MeshFilter>().sharedMesh = ms;
|
|
foreach (Mesh mesh in meshes) {
|
|
mesh.Clear();
|
|
DestroyImmediate(mesh);
|
|
}
|
|
MeshRenderer meshRendererCombine = combo.GetComponent<MeshFilter>().GetComponent<MeshRenderer>();
|
|
if (meshRendererCombine == null) meshRendererCombine = gameObject.AddComponent<MeshRenderer>();
|
|
Material[] materialsArray = materials.ToArray(typeof(Material)) as Material[];
|
|
meshRendererCombine.materials = materialsArray;
|
|
combined = combo.gameObject;
|
|
EnableRenderers(false);
|
|
combo.transform.parent = transform;
|
|
#if UNITY_EDITOR
|
|
if (generateLightmapUV) {
|
|
Unwrapping.GenerateSecondaryUVSet(combo.GetComponent<MeshFilter>().sharedMesh);
|
|
SerializedObject so = new SerializedObject (combo.GetComponent<MeshRenderer>());
|
|
so.FindProperty("m_ScaleInLightmap").floatValue = lightmapScale;
|
|
so.ApplyModifiedProperties();
|
|
}
|
|
#endif
|
|
combo.GetComponent<MeshFilter>().sharedMesh.RecalculateBounds();
|
|
vCount = combo.GetComponent<MeshFilter>().sharedMesh.vertexCount;
|
|
if (vCount > 65536) {
|
|
Debug.LogWarning("Vertex Count: " + vCount + "- Vertex Count too high, please divide mesh combine into more groups. Max 65536 for each mesh");
|
|
_canGenerateLightmapUV = false;
|
|
} else {
|
|
_canGenerateLightmapUV = true;
|
|
}
|
|
if (setStatic) combined.isStatic = true;
|
|
|
|
#if UNITY_EDITOR
|
|
EditorUtility.ClearProgressBar();
|
|
#endif
|
|
}
|
|
|
|
public int Contains(ArrayList l, Material n) {
|
|
for (int i = 0; i < l.Count; i++) {
|
|
if ((l[i] as Material) == n) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
}
|