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.

159 lines
6.7 KiB

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