CombineSkinMesh.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.SceneManagement;
  5. public class CombineSkinMesh : MonoBehaviour
  6. {
  7. public SkinnedMeshRenderer Body;
  8. public SkinnedMeshRenderer Kuzi;
  9. public SkinnedMeshRenderer Shangyi;
  10. public SkinnedMeshRenderer[] Clothes;
  11. // Start is called before the first frame update
  12. void Start()
  13. {
  14. //StartCombine();
  15. }
  16. // Update is called once per frame
  17. void Update()
  18. {
  19. }
  20. public void StartCombine()
  21. {
  22. Debug.Log("Combine");
  23. //SkinnedMeshRenderer[] meshes = new SkinnedMeshRenderer[] { Shangyi };
  24. CombineObject(Body.rootBone.gameObject, Clothes);
  25. }
  26. /// <summary>
  27. /// Only for merge materials.
  28. /// </summary>
  29. private const int COMBINE_TEXTURE_MAX = 512;
  30. private const string COMBINE_DIFFUSE_TEXTURE = "_MainTex";
  31. /// <summary>
  32. /// Combine SkinnedMeshRenderers together and share one skeleton.
  33. /// Merge materials will reduce the drawcalls, but it will increase the size of memory.
  34. /// </summary>
  35. /// <param name="skeleton">combine meshes to this skeleton(a gameobject)</param>
  36. /// <param name="meshes">meshes need to be merged</param>
  37. /// <param name="combine">merge materials or not</param>
  38. public void CombineObject(GameObject skeleton, SkinnedMeshRenderer[] meshes, bool combine = false)
  39. {
  40. // 收集所有关于skeleton的骨骼
  41. List<Transform> transforms = new List<Transform>();
  42. transforms.AddRange(skeleton.GetComponentsInChildren<Transform>(true));
  43. List<Material> materials = new List<Material>();//材质
  44. List<CombineInstance> combineInstances = new List<CombineInstance>();//网格
  45. List<Transform> bones = new List<Transform>();//骨骼
  46. // 下面的信息只用来合并材质(bool combine = true)
  47. List<Vector2[]> oldUV = null;
  48. Material newMaterial = null;
  49. Texture2D newDiffuseTex = null;
  50. // 收集网格部分信息
  51. for (int i = 0; i < meshes.Length; i++)
  52. {
  53. SkinnedMeshRenderer smr = meshes[i];
  54. // 收集材质
  55. materials.AddRange(smr.sharedMaterials);
  56. // 收集网格
  57. for (int sub = 0; sub < smr.sharedMesh.subMeshCount; sub++)
  58. {
  59. CombineInstance ci = new CombineInstance();
  60. ci.mesh = smr.sharedMesh;
  61. ci.subMeshIndex = sub;
  62. combineInstances.Add(ci);
  63. }
  64. // 收集骨骼
  65. for (int j = 0; j < smr.bones.Length; j++)
  66. {
  67. int tBase = 0;
  68. for (tBase = 0; tBase < transforms.Count; tBase++)
  69. {
  70. if (smr.bones[j].name.Equals(transforms[tBase].name))
  71. {
  72. bones.Add(transforms[tBase]);
  73. break;
  74. }
  75. }
  76. }
  77. }
  78. // 合并材质
  79. if (combine)
  80. {
  81. newMaterial = new Material(Shader.Find("Mobile/Diffuse"));
  82. oldUV = new List<Vector2[]>();
  83. // 合并贴图
  84. List<Texture2D> Textures = new List<Texture2D>();
  85. for (int i = 0; i < materials.Count; i++)
  86. {
  87. Textures.Add(materials[i].GetTexture(COMBINE_DIFFUSE_TEXTURE) as Texture2D);
  88. }
  89. newDiffuseTex = new Texture2D(COMBINE_TEXTURE_MAX, COMBINE_TEXTURE_MAX, TextureFormat.RGBA32, true);
  90. Rect[] uvs = newDiffuseTex.PackTextures(Textures.ToArray(), 0);
  91. newMaterial.mainTexture = newDiffuseTex;
  92. // 重置uv贴图
  93. Vector2[] uva, uvb;
  94. for (int j = 0; j < combineInstances.Count; j++)
  95. {
  96. uva = (Vector2[])(combineInstances[j].mesh.uv);
  97. uvb = new Vector2[uva.Length];
  98. for (int k = 0; k < uva.Length; k++)
  99. {
  100. uvb[k] = new Vector2((uva[k].x * uvs[j].width) + uvs[j].x, (uva[k].y * uvs[j].height) + uvs[j].y);
  101. }
  102. oldUV.Add(combineInstances[j].mesh.uv);
  103. combineInstances[j].mesh.uv = uvb;
  104. }
  105. }
  106. // 创建新的SkinnedMeshRenderer
  107. SkinnedMeshRenderer oldSKinned = skeleton.GetComponent<SkinnedMeshRenderer>();
  108. if (oldSKinned != null)
  109. {
  110. GameObject.DestroyImmediate(oldSKinned);
  111. }
  112. SkinnedMeshRenderer r = skeleton.AddComponent<SkinnedMeshRenderer>();
  113. r.sharedMesh = new Mesh();
  114. r.sharedMesh.CombineMeshes(combineInstances.ToArray(), combine, false);// 合并网格
  115. r.sharedMesh.name = "newMesh";
  116. r.bones = bones.ToArray();// 使用新骨骼
  117. if (combine)
  118. {
  119. r.material = newMaterial;
  120. for (int i = 0; i < combineInstances.Count; i++)
  121. {
  122. combineInstances[i].mesh.uv = oldUV[i];
  123. }
  124. }
  125. else
  126. {
  127. r.materials = materials.ToArray();
  128. }
  129. }
  130. }