using UnityEngine; using System.Collections; using System.Linq; using System.Collections.Generic; using UnityEditor.UI; public class MeshCombiner : MonoBehaviour { GameObject wallMesh; GameObject floorMesh; public void Awake() { } private void Start() { wallMesh = new GameObject("WallMesh", typeof(MeshFilter), typeof(Renderer)); floorMesh = new GameObject("FloorMesh", typeof(MeshFilter), typeof(Renderer)); print(transform.childCount); for (int i = transform.childCount - 1; i >= 0; --i) { Transform child = transform.GetChild(i); if (child.name == "Floor") child.SetParent(floorMesh.transform, true); else if (child.name == "Walls") child.SetParent(wallMesh.transform, true); } wallMesh.transform.parent = transform; floorMesh.transform.parent = transform; CombineWalls(); CombineFloor(); ClearChildren(floorMesh.transform); ClearChildren(wallMesh.transform); SplitMesh(floorMesh.GetComponent()); SplitMesh(wallMesh.GetComponent()); for (int i = 0; i < floorMesh.transform.childCount; i++) { Simplify(floorMesh.transform.GetChild(i).GetComponent()); } for (int i = 0; i < wallMesh.transform.childCount; i++) { Simplify(wallMesh.transform.GetChild(i).GetComponent()); } } void ClearChildren(Transform t) { for(int i=0; i(); filter.mesh=mf.mesh.GetSubmesh(i); Renderer r = gO.AddComponent(); r.material = mf.gameObject.GetComponent().materials[i]; MeshCollider c = gO.AddComponent(); c.sharedMesh = filter.mesh; } Destroy(mf.gameObject.GetComponent()); Destroy(mf.gameObject.GetComponent()); } private void CombineWalls() { Vector3 basePosition = transform.position; Quaternion baseRotation = transform.rotation; transform.position = Vector3.zero; transform.rotation = Quaternion.identity; ArrayList materials = new ArrayList(); ArrayList combineInstanceArrays = new ArrayList(); MeshFilter[] meshFilters = wallMesh.GetComponentsInChildren(); //Linq solution to make sure we don't combine any of the doors(a door is easily identifiable by it's rigidbody component, so we look for that). meshFilters = meshFilters.Where((source, index) => !(source.transform.name == "FloorMesh" || source.transform.name == "WallMesh" || source.transform.GetComponent() || source.transform.GetComponentInParent())).ToArray(); foreach (MeshFilter meshFilter in meshFilters) { MeshRenderer meshRenderer = meshFilter.GetComponent(); if (!meshRenderer || !meshFilter.sharedMesh || meshRenderer.sharedMaterials.Length != meshFilter.sharedMesh.subMeshCount) { print(meshFilter.gameObject.name); continue; } for (int s = 0; s < meshFilter.sharedMesh.subMeshCount; s++) { if (meshRenderer.sharedMaterials[s]){ int materialArrayIndex = Contains(materials, meshRenderer.sharedMaterials[s].name); if (materialArrayIndex == -1) { materials.Add(meshRenderer.sharedMaterials[s]); materialArrayIndex = materials.Count - 1; } combineInstanceArrays.Add(new ArrayList()); CombineInstance combineInstance = new CombineInstance(); combineInstance.transform = meshRenderer.transform.localToWorldMatrix; combineInstance.subMeshIndex = s; combineInstance.mesh = meshFilter.sharedMesh; (combineInstanceArrays[materialArrayIndex] as ArrayList).Add(combineInstance); } } } // Get / Create mesh filter & renderer MeshFilter meshFilterCombine = wallMesh.GetComponent(); if (meshFilterCombine == null) { meshFilterCombine = wallMesh.AddComponent(); } MeshRenderer meshRendererCombine = gameObject.GetComponent(); if (meshRendererCombine == null) { meshRendererCombine = wallMesh.AddComponent(); } // Combine by material index into per-material meshes // also, Create CombineInstance array for next step 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; } // Combine into one meshFilterCombine.sharedMesh = new Mesh(); meshFilterCombine.sharedMesh.CombineMeshes(combineInstances, false, false); // Destroy other meshes foreach (Mesh oldMesh in meshes) { oldMesh.Clear(); DestroyImmediate(oldMesh); } // Assign materials Material[] materialsArray = materials.ToArray(typeof(Material)) as Material[]; meshRendererCombine.materials = materialsArray; foreach (MeshFilter meshFilter in meshFilters) { if (!meshFilter || meshFilter.transform.GetComponent() || meshFilter.transform.GetComponentInParent() || meshFilter.transform.GetComponentInChildren()) continue; print(meshFilter.gameObject.transform.parent.name); DestroyImmediate(meshFilter.gameObject.transform.parent.gameObject); } wallMesh.transform.position = basePosition; wallMesh.transform.rotation = baseRotation; wallMesh.AddComponent().sharedMesh = wallMesh.GetComponent().sharedMesh; } private void CombineFloor() { Vector3 basePosition = transform.position; Quaternion baseRotation = transform.rotation; transform.position = Vector3.zero; transform.rotation = Quaternion.identity; ArrayList materials = new ArrayList(); ArrayList combineInstanceArrays = new ArrayList(); MeshFilter[] meshFilters = floorMesh.GetComponentsInChildren(); //Linq solution to make sure we don't combine any of the doors(a door is easily identifiable by it's rigidbody component, so we look for that). meshFilters = meshFilters.Where((source, index) => !(source.transform.name=="FloorMesh" || source.transform.name=="WallMesh" || source.transform.GetComponent() || source.transform.GetComponentInParent())).ToArray(); foreach (MeshFilter meshFilter in meshFilters) { MeshRenderer meshRenderer = meshFilter.GetComponent(); if (!meshRenderer || !meshFilter.sharedMesh || meshRenderer.sharedMaterials.Length != meshFilter.sharedMesh.subMeshCount) { continue; } for (int s = 0; s < meshFilter.sharedMesh.subMeshCount; s++) { if (meshRenderer.sharedMaterials[s]) { int materialArrayIndex = Contains(materials, meshRenderer.sharedMaterials[s].name); if (materialArrayIndex == -1) { materials.Add(meshRenderer.sharedMaterials[s]); materialArrayIndex = materials.Count - 1; } combineInstanceArrays.Add(new ArrayList()); CombineInstance combineInstance = new CombineInstance(); combineInstance.transform = meshRenderer.transform.localToWorldMatrix; combineInstance.subMeshIndex = s; combineInstance.mesh = meshFilter.sharedMesh; (combineInstanceArrays[materialArrayIndex] as ArrayList).Add(combineInstance); } } } // Get / Create mesh filter & renderer MeshFilter meshFilterCombine = floorMesh.GetComponent(); if (meshFilterCombine == null) { meshFilterCombine = floorMesh.AddComponent(); } MeshRenderer meshRendererCombine = gameObject.GetComponent(); if (meshRendererCombine == null) { meshRendererCombine = floorMesh.AddComponent(); } // Combine by material index into per-material meshes // also, Create CombineInstance array for next step 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; } // Combine into one meshFilterCombine.sharedMesh = new Mesh(); meshFilterCombine.sharedMesh.CombineMeshes(combineInstances, false, false); // Destroy other meshes foreach (Mesh oldMesh in meshes) { oldMesh.Clear(); DestroyImmediate(oldMesh); } // Assign materials Material[] materialsArray = materials.ToArray(typeof(Material)) as Material[]; meshRendererCombine.materials = materialsArray; foreach (MeshFilter meshFilter in meshFilters) { if (!meshFilter || meshFilter.transform.GetComponent() || meshFilter.transform.GetComponentInParent() || meshFilter.transform.GetComponentInChildren()) continue; DestroyImmediate(meshFilter.gameObject.transform.parent.gameObject); } floorMesh.transform.position = basePosition; floorMesh.transform.rotation = baseRotation; floorMesh.AddComponent().sharedMesh = floorMesh.GetComponent().sharedMesh; } private int Contains(ArrayList searchList, string searchName) { for (int i = 0; i < searchList.Count; i++) { if (((Material)searchList[i]).name == searchName) { return i; } } return -1; } }