CombineSkinMesh.cs 5.2 KB

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