创建如图所示的对象结构,parent为空对象,然后将下面的代码挂载到parent对象上运行即可。
using UnityEngine;
using System.Collections; public class CombineMeshAndMaterials : MonoBehaviour
{
void Start()
{
CombineMesh();
}
void CombineMesh()
{
//收集要合并的贴图
MeshRenderer[] oldMRArray = GetComponentsInChildren<MeshRenderer>();
Material[] oldMArray = new Material[oldMRArray.Length];
Texture2D[] textures = new Texture2D[oldMRArray.Length];
for (int i = , iMax = oldMRArray.Length; i < iMax; ++i)
{
oldMArray[i] = oldMRArray[i].sharedMaterial;
Texture2D t2d = oldMArray[i].GetTexture("_MainTex") as Texture2D;
Texture2D _t2d = new Texture2D(t2d.width, t2d.height, TextureFormat.ARGB32, false);
_t2d.SetPixels(t2d.GetPixels(, , t2d.width, t2d.height));
_t2d.Apply();
textures[i] = _t2d;
} //创建合并后的材质
MeshRenderer newMR = gameObject.AddComponent<MeshRenderer>();
Material newM = new Material(oldMArray[].shader);
newM.CopyPropertiesFromMaterial(oldMArray[]);
newMR.sharedMaterial = newM; //创建合并后的贴图,
Texture2D newTex = new Texture2D(, );
newM.SetTexture("_MainTex", newTex); //将合并后的贴图赋给合并后的材质 //重新计算贴图UV
MeshFilter[] oldMF = GetComponentsInChildren<MeshFilter>();
CombineInstance[] combines = new CombineInstance[oldMF.Length];
Rect[] rects = newTex.PackTextures(textures, , ); //贴图打包 ,矩形的数组包含每个输入的纹理的UV坐标
for (int i = , iMax = oldMF.Length; i < iMax; ++i)
{
Rect rect = rects[i];
Mesh mesh = oldMF[i].mesh;
Vector2[] newUVs = new Vector2[mesh.uv.Length]; //刷新uv
for (int j = , jMax = mesh.uv.Length; j < jMax; ++j)
{
//如果这里看不太懂,说明对uv的确切含义不太明白
//uv是一个比值,u = 横向第u个像素/原始贴图的宽度 v = 竖向第v个像素/原始贴图的高度
//rect.x : 原贴图在合并后的贴图的 x 坐标, rect.y : 原贴图在合并后的贴图的 y 坐标
newUVs[j].x = mesh.uv[j].x * rect.width + rect.x;
newUVs[j].y = mesh.uv[j].y * rect.height + rect.y;
}
mesh.uv = newUVs;
combines[i].mesh = mesh;
combines[i].transform = oldMF[i].transform.localToWorldMatrix; //没有这句,合并后的网格无法看到
oldMF[i].gameObject.SetActive(false);
} //创建合并后的网格
MeshFilter newMF = gameObject.AddComponent<MeshFilter>();
Mesh newMesh = new Mesh();
newMesh.CombineMeshes(combines, true, true);
newMF.mesh = newMesh;
}
}