做项目的时候,有的时候我们需要把多个Mesh合并起来,只是为了让我们做起来的时候更方便些。下面是Mesh合并的代码,支持动态合并和保存到文件。
using UnityEngine;
using System.Collections.Generic;
namespace LDFW.Model
{
public class MeshCombiner : MonoBehaviour
{
public List<Transform> subMeshTransformList0;
public List<Transform> subMeshTransformList1;
public List<Transform> subMeshTransformList2;
public List<Transform> subMeshTransformList3;
public List<Transform> multiSubMeshTransformList;
public string meshSavePath = "Assets/";
public Mesh CombineMeshesWithSameUV(List<Transform> transformList)
{
if (transformList == null || transformList.Count <= 0)
{
Debug.LogError("Input transform list is null!");
return null;
}
Mesh newMesh = new Mesh();
List<Vector3> vertexList = new List<Vector3>();
List<Vector2> uvList = new List<Vector2>();
List<int> triangleList = new List<int>();
int currentVertexListLength = 0;
foreach (var trans in transformList)
{
if (trans == null)
continue;
MeshFilter meshFilter = trans.GetComponent<MeshFilter>();
if (meshFilter == null)
continue;
Mesh mesh = meshFilter.mesh;
if (mesh == null)
continue;
currentVertexListLength = vertexList.Count;
foreach (var vertex in mesh.vertices)
vertexList.Add(transform.InverseTransformPoint(trans.TransformPoint(vertex)));
foreach (var uv in mesh.uv)
uvList.Add(uv);
foreach (var triangleVertexIndex in mesh.triangles)
triangleList.Add(currentVertexListLength + triangleVertexIndex);
}
newMesh.vertices = vertexList.ToArray();
newMesh.uv = uvList.ToArray();
newMesh.triangles = triangleList.ToArray();
return newMesh;
}
public Mesh CombineSubMeshes(List<Transform> subMesh0, List<Transform> subMesh1, List<Transform> subMesh2, List<Transform> subMesh3)
{
Mesh[] subMeshArray = new Mesh[4]
{
CombineMeshesWithSameUV(subMesh0),
CombineMeshesWithSameUV(subMesh1),
CombineMeshesWithSameUV(subMesh2),
CombineMeshesWithSameUV(subMesh3),
};
Mesh newMesh = new Mesh();
List<Vector3> vertexList = new List<Vector3>();
List<Vector2> uvList = new List<Vector2>();
List<int> triangleIndexList = new List<int>();
int currentVertexCount = 0;
Mesh currentMesh;
Vector3[] currentMeshVertices;
Vector2[] currentMeshUV;
int[] currentMeshTriangleIndices;
List<int>[] subMeshTriangleListArray = new List<int>[4];
int subMeshCount = 0;
for (int i = 0; i < 4; i++)
{
currentMesh = subMeshArray[i];
subMeshTriangleListArray[i] = new List<int>();
if (currentMesh == null)
continue;
subMeshCount++;
currentVertexCount = vertexList.Count;
currentMeshVertices = currentMesh.vertices;
currentMeshUV = currentMesh.uv;
currentMeshTriangleIndices = currentMesh.triangles;
foreach (var vertex in currentMeshVertices)
vertexList.Add(vertex);
foreach (var uv in currentMeshUV)
uvList.Add(uv);
foreach (var triangleIndex in currentMeshTriangleIndices)
{
subMeshTriangleListArray[i].Add(currentVertexCount + triangleIndex);
triangleIndexList.Add(currentVertexCount + triangleIndex);
}
}
newMesh.vertices = vertexList.ToArray();
newMesh.subMeshCount = subMeshCount;
if (subMeshCount >= 1)
{
newMesh.uv = uvList.ToArray();
newMesh.SetIndices(subMeshTriangleListArray[0].ToArray(), MeshTopology.Triangles, 0);
}
if (subMeshCount >= 2)
{
newMesh.uv2 = uvList.ToArray();
newMesh.SetIndices(subMeshTriangleListArray[1].ToArray(), MeshTopology.Triangles, 1);
}
if (subMeshCount >= 3)
{
newMesh.uv3 = uvList.ToArray();
newMesh.SetIndices(subMeshTriangleListArray[2].ToArray(), MeshTopology.Triangles, 2);
}
if (subMeshCount >= 4)
{
newMesh.uv4 = uvList.ToArray();
newMesh.SetIndices(subMeshTriangleListArray[3].ToArray(), MeshTopology.Triangles, 3);
}
newMesh.RecalculateBounds();
newMesh.RecalculateNormals();
System.GC.Collect();
return newMesh;
}
public Mesh CombineMultiSubMeshes(List<Transform> multiSubMeshList)
{
Mesh newMesh = new Mesh();
Mesh currentMesh = null;
int totalSubMeshCount = 0;
List<Vector3> vertices = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
List<Vector2>[] uvList= new List<Vector2>[4];
for (int i = 0; i < 4; i++)
uvList[i] = new List<Vector2>();
List<int>[] triangleList = new List<int>[4];
for (int i = 0; i < 4; i++)
triangleList[i] = new List<int>();
// i: multiSubMeshList index
// totalSubMeshCount: total submesh count
//
for (int i = 0; totalSubMeshCount < 4 && i < multiSubMeshList.Count; i++)
{
if (multiSubMeshList[i] == null)
continue;
currentMesh = multiSubMeshList[i].GetComponent<MeshFilter>().mesh;
if (currentMesh == null)
continue;
Debug.Log(MeshInfoExtractor.GetMeshVerticesData(currentMesh));
Debug.Log(MeshInfoExtractor.GetMeshUVData(currentMesh));
Debug.Log(MeshInfoExtractor.GetTriangleData(currentMesh));
Debug.Log(MeshInfoExtractor.GetSubmeshData(currentMesh));
int currentSubMeshCount = currentMesh.subMeshCount;
if (totalSubMeshCount + currentSubMeshCount > 4)
break;
int currentVertexCount = vertices.Count;
// concatenate vertices and uvs
AddVertices(vertices, currentMesh.vertices, transform, multiSubMeshList[i]);
AddUVs(uvs, currentMesh.uv);
// Extract submesh triangles
int[][] currentMeshTriangleArray = new int[currentSubMeshCount][];
for (int j = 0; j < currentSubMeshCount; j++)
currentMeshTriangleArray[j] = currentMesh.GetTriangles(j);
// Concatenate submesh triangles
int currentMeshTriangleArrayIndex = 0;
for (int j = totalSubMeshCount; j < totalSubMeshCount + currentSubMeshCount; j++)
{
if (currentMeshTriangleArray[currentMeshTriangleArrayIndex] != null)
AddMeshTriangle(triangleList[j], currentMeshTriangleArray[currentMeshTriangleArrayIndex], currentVertexCount);
currentMeshTriangleArrayIndex++;
}
totalSubMeshCount += currentSubMeshCount;
}
Debug.Log("Vertices length = " + vertices.Count);
Debug.Log("UVs length = " + uvList[0].Count + ", " + uvList[1].Count + ", " + uvList[2].Count + ", " + uvList[3].Count);
Debug.Log("Triangles length = " + triangleList[0].Count + ", " + triangleList[1].Count + ", " + triangleList[2].Count + ", " + triangleList[3].Count);
newMesh.SetVertices(vertices);
newMesh.uv = uvs.ToArray();
newMesh.subMeshCount = totalSubMeshCount;
for (int i = 0; i < totalSubMeshCount; i++)
newMesh.SetIndices(triangleList[i].ToArray(), MeshTopology.Triangles, i);
newMesh.RecalculateBounds();
newMesh.RecalculateNormals();
System.GC.Collect();
return newMesh;
}
private void AddVertices(List<Vector3> targetVertices, Vector3[] newVertices, Transform newParent, Transform oldParent)
{
if (newVertices != null)
{
foreach (var vec3 in newVertices)
targetVertices.Add(newParent.InverseTransformPoint(oldParent.TransformPoint(vec3)));
}
}
private void AddUVs(List<Vector2> targetUVs, Vector2[] newUVs)
{
if (newUVs != null)
{
foreach (var vec2 in newUVs)
targetUVs.Add(vec2);
}
}
private void AddMeshUV(List<Vector2> targetUV, Vector2[] uvArray)
{
if (uvArray != null)
{
foreach (var vec2 in uvArray)
targetUV.Add(vec2);
}
}
private void AddMeshTriangle(List<int> targetTriangles, int[] triangleArray, int triangleIndexOffset)
{
if (triangleArray != null)
{
for (int i = 0; i < triangleArray.Length; i++)
{
targetTriangles.Add(triangleArray[i] + triangleIndexOffset);
}
}
}
}
}