You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
6.8 KiB

5 years ago
5 years ago
5 years ago
  1. /****************************************
  2. Simple Mesh Combine
  3. Copyright Unluck Software
  4. www.chemicalbliss.com
  5. *****************************************/
  6. //Add script to the parent gameObject, then click combine
  7. using UnityEngine;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. #if UNITY_EDITOR
  11. using UnityEditor;
  12. #endif
  13. [AddComponentMenu("Simple Mesh Combine")]
  14. public class SimpleMeshCombine : MonoBehaviour {
  15. public GameObject[] combinedGameOjects; //Stores gameObjects that has been merged, mesh renderer disabled
  16. public GameObject combined; //Stores the combined mesh gameObject
  17. public string meshName = "Combined_Meshes"; //Asset name when saving as prefab
  18. public bool _canGenerateLightmapUV;
  19. public int vCount;
  20. public bool generateLightmapUV;
  21. public float lightmapScale = 1f;
  22. public GameObject copyTarget;
  23. public bool destroyOldColliders;
  24. public bool keepStructure = true;
  25. public Mesh autoOverwrite;
  26. public bool setStatic = true;
  27. public void EnableRenderers(bool e) {
  28. for (int i = 0; i < combinedGameOjects.Length; i++) {
  29. if (combinedGameOjects[i] == null) break;
  30. Renderer renderer = combinedGameOjects[i].GetComponent<Renderer>();
  31. if (renderer != null) renderer.enabled = e;
  32. }
  33. }
  34. //Returns a meshFilter[] list of all renderer enabled meshfilters(so that it does not merge disabled meshes, useful when there are invisible box colliders)
  35. public MeshFilter[] FindEnabledMeshes() {
  36. MeshFilter[] renderers = null;
  37. int count = 0;
  38. renderers = transform.GetComponentsInChildren<MeshFilter>();
  39. //count all the enabled meshrenderers in children
  40. for (int i = 0; i < renderers.Length; i++) {
  41. if ((renderers[i].GetComponent<MeshRenderer>() != null) && renderers[i].GetComponent<MeshRenderer>().enabled)
  42. count++;
  43. }
  44. MeshFilter[] meshfilters = new MeshFilter[count];//creates a new array with the correct length
  45. count = 0;
  46. //adds all enabled meshes to the array
  47. for (int ii = 0; ii < renderers.Length; ii++) {
  48. if ((renderers[ii].GetComponent<MeshRenderer>() != null) && renderers[ii].GetComponent<MeshRenderer>().enabled) {
  49. meshfilters[count] = renderers[ii];
  50. count++;
  51. }
  52. }
  53. return meshfilters;
  54. }
  55. public void CombineMeshes() {
  56. GameObject combo = new GameObject();
  57. combo.name = "_Combined Mesh [" + name + "]";
  58. combo.gameObject.AddComponent<MeshFilter>();
  59. combo.gameObject.AddComponent<MeshRenderer>();
  60. MeshFilter[] meshFilters = null;
  61. meshFilters = FindEnabledMeshes();
  62. ArrayList materials = new ArrayList();
  63. ArrayList combineInstanceArrays = new ArrayList();
  64. combinedGameOjects = new GameObject[meshFilters.Length];
  65. for (int i = 0; i < meshFilters.Length; i++) {
  66. combinedGameOjects[i] = meshFilters[i].gameObject;
  67. MeshRenderer meshRenderer = meshFilters[i].GetComponent<MeshRenderer>();
  68. meshFilters[i].transform.gameObject.GetComponent<Renderer>().enabled = false;
  69. if (meshFilters[i].sharedMesh == null) {
  70. #if UNITY_EDITOR
  71. Debug.LogWarning("SimpleMeshCombine : " + meshFilters[i].gameObject + " [Mesh Filter] has no [Mesh], mesh will not be included in combine..");
  72. #endif
  73. break;
  74. }
  75. for (int o = 0; o < meshFilters[i].sharedMesh.subMeshCount; o++) {
  76. if (meshRenderer == null) {
  77. #if UNITY_EDITOR
  78. Debug.LogWarning("SimpleMeshCombine : " + meshFilters[i].gameObject + "has a [Mesh Filter] but no [Mesh Renderer], mesh will not be included in combine.");
  79. #endif
  80. break;
  81. }
  82. if (o < meshRenderer.sharedMaterials.Length && o < meshFilters[i].sharedMesh.subMeshCount) {
  83. int materialArrayIndex = Contains(materials, meshRenderer.sharedMaterials[o]);
  84. if (materialArrayIndex == -1) {
  85. materials.Add(meshRenderer.sharedMaterials[o]);
  86. materialArrayIndex = materials.Count - 1;
  87. }
  88. combineInstanceArrays.Add(new ArrayList());
  89. CombineInstance combineInstance = new CombineInstance();
  90. combineInstance.transform = meshRenderer.transform.localToWorldMatrix;
  91. //Fix for Unity 2017 Bug
  92. #if UNITY_2017
  93. if (meshFilters[i].sharedMesh.subMeshCount > 1) combineInstance.mesh = SubMeshFix.GetSubmesh(meshFilters[i].sharedMesh,o);
  94. else {
  95. combineInstance.mesh = meshFilters[i].sharedMesh;
  96. }
  97. #else
  98. combineInstance.mesh = meshFilters[i].sharedMesh;
  99. combineInstance.subMeshIndex = o;
  100. #endif
  101. (combineInstanceArrays[materialArrayIndex] as ArrayList).Add(combineInstance);
  102. }
  103. #if UNITY_EDITOR
  104. else {
  105. Debug.LogWarning("Simple Mesh Combine: GameObject [ " + meshRenderer.gameObject.name + " ] is missing a material (Mesh or sub-mesh ignored from combine)");
  106. }
  107. #endif
  108. }
  109. #if UNITY_EDITOR
  110. EditorUtility.DisplayProgressBar("Combining", "", (float)i);
  111. #endif
  112. }
  113. Mesh[] meshes = new Mesh[materials.Count];
  114. CombineInstance[] combineInstances = new CombineInstance[materials.Count];
  115. for (int m = 0; m < materials.Count; m++) {
  116. CombineInstance[] combineInstanceArray = (combineInstanceArrays[m] as ArrayList).ToArray(typeof(CombineInstance)) as CombineInstance[];
  117. meshes[m] = new Mesh();
  118. meshes[m].CombineMeshes(combineInstanceArray, true, true);
  119. combineInstances[m] = new CombineInstance();
  120. combineInstances[m].mesh = meshes[m];
  121. combineInstances[m].subMeshIndex = 0;
  122. }
  123. Mesh ms = combo.GetComponent<MeshFilter>().sharedMesh = new Mesh();
  124. ms.Clear();
  125. ms.CombineMeshes(combineInstances, false, false);
  126. combo.GetComponent<MeshFilter>().sharedMesh = ms;
  127. foreach (Mesh mesh in meshes) {
  128. mesh.Clear();
  129. DestroyImmediate(mesh);
  130. }
  131. MeshRenderer meshRendererCombine = combo.GetComponent<MeshFilter>().GetComponent<MeshRenderer>();
  132. if (meshRendererCombine == null) meshRendererCombine = gameObject.AddComponent<MeshRenderer>();
  133. Material[] materialsArray = materials.ToArray(typeof(Material)) as Material[];
  134. meshRendererCombine.materials = materialsArray;
  135. combined = combo.gameObject;
  136. EnableRenderers(false);
  137. combo.transform.parent = transform;
  138. #if UNITY_EDITOR
  139. if (generateLightmapUV) {
  140. Unwrapping.GenerateSecondaryUVSet(combo.GetComponent<MeshFilter>().sharedMesh);
  141. SerializedObject so = new SerializedObject (combo.GetComponent<MeshRenderer>());
  142. so.FindProperty("m_ScaleInLightmap").floatValue = lightmapScale;
  143. so.ApplyModifiedProperties();
  144. }
  145. #endif
  146. combo.GetComponent<MeshFilter>().sharedMesh.RecalculateBounds();
  147. vCount = combo.GetComponent<MeshFilter>().sharedMesh.vertexCount;
  148. if (vCount > 65536) {
  149. Debug.LogWarning("Vertex Count: " + vCount + "- Vertex Count too high, please divide mesh combine into more groups. Max 65536 for each mesh");
  150. _canGenerateLightmapUV = false;
  151. } else {
  152. _canGenerateLightmapUV = true;
  153. }
  154. if (setStatic) combined.isStatic = true;
  155. #if UNITY_EDITOR
  156. EditorUtility.ClearProgressBar();
  157. #endif
  158. }
  159. public int Contains(ArrayList l, Material n) {
  160. for (int i = 0; i < l.Count; i++) {
  161. if ((l[i] as Material) == n) {
  162. return i;
  163. }
  164. }
  165. return -1;
  166. }
  167. }