本人是个小白,可是有个作技术的理想。性能
关于合并网格和贴图这个问题困扰了我很久,问群友,逛论坛,翻帖子,或者说是个人愚笨吧,不过通过努力仍是我解决了,测试经过,一个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 }