using UnityEngine; namespace Gameplay.Utils { public class LTCombie : MonoBehaviour { private Mesh _CreateMeshFromSubMesh(Mesh sourceMesh, int subMeshIndex) { // 创建一个新的网格 Mesh newMesh = new Mesh(); var subMeshDescriptor = sourceMesh.GetSubMesh(subMeshIndex); // 获取来源网格的顶点、法线、切线和UV数组 Vector3[] vertices = sourceMesh.vertices; Vector3[] normals = sourceMesh.normals; Vector4[] tangents = sourceMesh.tangents; Vector2[] uv = sourceMesh.uv; // 从来源网格中获取指定子网格的三角形索引数组 int[] triangles = sourceMesh.GetTriangles(subMeshIndex); // 根据子网格描述符中的顶点数量,创建新网格的顶点、法线、切线和UV数组 Vector3[] newVertices = new Vector3[subMeshDescriptor.vertexCount]; Vector3[] newNormals = new Vector3[subMeshDescriptor.vertexCount]; Vector4[] newTangents = new Vector4[subMeshDescriptor.vertexCount]; Vector2[] newUV = new Vector2[subMeshDescriptor.vertexCount]; // 根据子网格描述符中的三角形索引数量,创建新网格的三角形索引数组 int[] newTriangles = new int[triangles.Length]; // 从来源网格的数组中复制数据到新网格的数组 for (int i = 0; i < subMeshDescriptor.vertexCount; i++) { newVertices[i] = vertices[subMeshDescriptor.firstVertex + i]; newNormals[i] = normals[subMeshDescriptor.firstVertex + i]; newTangents[i] = tangents[subMeshDescriptor.firstVertex + i]; newUV[i] = uv[subMeshDescriptor.firstVertex + i]; } for (int i = 0; i < subMeshDescriptor.indexCount; i++) { newTriangles[i] = triangles[i] - subMeshDescriptor.firstVertex; } // 设置新网格的顶点、法线、切线和UV数组,以及三角形索引数组 newMesh.vertices = newVertices; newMesh.normals = newNormals; newMesh.tangents = newTangents; newMesh.uv = newUV; newMesh.triangles = newTriangles; return newMesh; } [ContextMenu("ManualCombine")] public void ManualCombine() { // combine branch { var allMeshRenders = GetComponentsInChildren(); var material = allMeshRenders[0].sharedMaterials[0]; var combineInstanceArrays = new CombineInstance[allMeshRenders.Length]; for (var i = 0; i < allMeshRenders.Length; i++) { var meshFilter = allMeshRenders[i].GetComponent(); var getMesh = meshFilter.sharedMesh; combineInstanceArrays[i].mesh = _CreateMeshFromSubMesh(getMesh, 0); combineInstanceArrays[i].transform = meshFilter.transform.localToWorldMatrix; } var newMesh = new Mesh(); newMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; newMesh.CombineMeshes(combineInstanceArrays, true, true); var newGameObject = new GameObject("CombinedMesh_branch"); var newMeshFilter = newGameObject.AddComponent(); newMeshFilter.sharedMesh = newMesh; var newMeshRenderer = newGameObject.AddComponent(); newMeshRenderer.sharedMaterial = material; newGameObject.transform.localPosition = Vector3.zero; newGameObject.transform.localRotation = Quaternion.identity; newGameObject.transform.localScale = Vector3.one; // transform.gameObject.SetActive(false); #if UNITY_EDITOR // save mesh to asset UnityEditor.AssetDatabase.CreateAsset(newMesh, "Assets/CombinedMesh_branch.asset"); UnityEditor.AssetDatabase.SaveAssets(); // save prefab to asset UnityEditor.PrefabUtility.SaveAsPrefabAsset(newGameObject, "Assets/CombinedMesh_branch.prefab"); #endif } // combine trunk { var allMeshRenders = GetComponentsInChildren(); var material = allMeshRenders[0].sharedMaterials[1]; var combineInstanceArrays = new CombineInstance[allMeshRenders.Length]; for (var i = 0; i < allMeshRenders.Length; i++) { var meshFilter = allMeshRenders[i].GetComponent(); var getMesh = meshFilter.sharedMesh; combineInstanceArrays[i].mesh = _CreateMeshFromSubMesh(getMesh, 1); combineInstanceArrays[i].transform = meshFilter.transform.localToWorldMatrix; } var newMesh = new Mesh(); newMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; newMesh.CombineMeshes(combineInstanceArrays, true, true); var newGameObject = new GameObject("CombinedMesh_trunk"); var newMeshFilter = newGameObject.AddComponent(); newMeshFilter.sharedMesh = newMesh; var newMeshRenderer = newGameObject.AddComponent(); newMeshRenderer.sharedMaterial = material; newGameObject.transform.localPosition = Vector3.zero; newGameObject.transform.localRotation = Quaternion.identity; newGameObject.transform.localScale = Vector3.one; #if UNITY_EDITOR // save mesh to asset UnityEditor.AssetDatabase.CreateAsset(newMesh, "Assets/CombinedMesh_trunk.asset"); UnityEditor.AssetDatabase.SaveAssets(); // save prefab to asset UnityEditor.PrefabUtility.SaveAsPrefabAsset(newGameObject, "Assets/CombinedMesh_trunk.prefab"); #endif } transform.gameObject.SetActive(false); } } }