本人是個小白,可是有個作技術的理想。性能
關於合併網格和貼圖這個問題困擾了我很久,問羣友,逛論壇,翻帖子,或者說是個人愚笨吧,不過通過努力仍是我解決了,測試經過,一個8drawcall的模型,合併後降到2drawcall,固然如今移動設備的性能都比較高了,沒必要過多糾結於drawcall,若是沒這須要請路過吧。。。測試
好的,廢話很少說,我把代碼貼出來。this
1 using UnityEngine; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.IO; 5 6 public class CombineMesher : MonoBehaviour 7 { 8 // Use this for initialization 9 void Start() 10 { 11 Combine(transform); 12 } 13 14 // Update is called once per frame 15 void Update() 16 { 17 18 } 19 20 21 public Transform Combine(Transform root) 22 { 23 float startTime = Time.realtimeSinceStartup; 24 25 // The SkinnedMeshRenderers that will make up a character will be 26 // combined into one SkinnedMeshRenderers using one material. 27 // This will speed up rendering the resulting character. 28 // note:each SkinnedMeshRenderer must share a same material 29 List<CombineInstance> combineInstances = new List<CombineInstance>(); 30 List<Material> materials = new List<Material>(); 31 Material material = null; 32 List<Transform> bones = new List<Transform>(); 33 Transform[] transforms = root.GetComponentsInChildren<Transform>(); 34 List<Texture2D> textures = new List<Texture2D>(); 35 int width = 0; 36 int height = 0; 37 38 int uvCount = 0; 39 40 List<Vector2[]> uvList = new List<Vector2[]>(); 41 42 foreach (SkinnedMeshRenderer smr in root.GetComponentsInChildren<SkinnedMeshRenderer>()) 43 { 44 if (material == null) 45 material = Instantiate(smr.sharedMaterial) as Material; 46 for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++) 47 { 48 CombineInstance ci = new CombineInstance(); 49 ci.mesh = smr.sharedMesh; 50 ci.subMeshIndex = sub; 51 combineInstances.Add(ci); 52 } 53 54 uvList.Add(smr.sharedMesh.uv); 55 uvCount += smr.sharedMesh.uv.Length; 56 57 if (smr.material.mainTexture != null) 58 { 59 textures.Add(smr.renderer.material.mainTexture as Texture2D); 60 width += smr.renderer.material.mainTexture.width; 61 height += smr.renderer.material.mainTexture.height; 62 } 63 64 // we need to recollect references to the bones we are using 65 foreach (Transform bone in smr.bones) 66 { 67 foreach (Transform transform in transforms) 68 { 69 if (transform.name != bone.name) continue; 70 bones.Add(transform); 71 break; 72 } 73 } 74 Object.Destroy(smr.gameObject); 75 } 76 77 // Obtain and configure the SkinnedMeshRenderer attached to 78 // the character base. 79 SkinnedMeshRenderer r = root.gameObject.GetComponent<SkinnedMeshRenderer>(); 80 if (!r) 81 r = root.gameObject.AddComponent<SkinnedMeshRenderer>(); 82 83 r.sharedMesh = new Mesh(); 84 85 //only set mergeSubMeshes true will combine meshs into single submesh 86 r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, false); 87 r.bones = bones.ToArray(); 88 r.material = material; 89 90 Texture2D skinnedMeshAtlas = new Texture2D(1024, 512); 91 Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0); 92 Vector2[] atlasUVs = new Vector2[uvCount]; 93 94 //as combine textures into single texture,so need recalculate uvs 95 96 int j = 0; 97 for (int i = 0; i < uvList.Count; i++) 98 { 99 foreach (Vector2 uv in uvList[i]) 100 { 101 atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x); 102 atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y); 103 j++; 104 } 105 } 106 107 r.material.mainTexture = skinnedMeshAtlas; 108 r.sharedMesh.uv = atlasUVs; 109 110 Debug.Log("combine meshes takes : " + (Time.realtimeSinceStartup - startTime) * 1000 + " ms"); 111 return root; 112 } 113 }