网络上讲解mesh合并的人很多,但是讲解合并Material 的少,讲解合并贴图的更少!!!
下面就挨个示例说明一下
material | shader | mesh | 结果 |
---|---|---|---|
相同 | 相同 | 合并 | 只合并mesh,共用material |
- | – | - | - |
不同 | 相同但贴图不同 | 合并 | 合并贴图,共用material |
- | – | - | - |
不同 | 不相同 | 合并 | 将materia合并l到合并后的mesh上 |
- | – | - | - |
一.Mesh合并
下图是合并mesh,不合并mesh的比较
二。函数说明:
Mesh.CombineMeshes(meshs,true,true):
在此处的第二个参数bool: true表示会合并为一个mesh;fasle表示各mesh是单独的
三.合并:material不同,shader不同的情况
Mesh.CombineMeshes(meshs,false):
此处的合并后mesh的个数和material的个数要对应起来
true和false的效果是不一样的:
[MenuItem("测试/combineMesh_DiffMat")]
public static void CombineMeshDiffMat()
{
var selectObj = Selection.activeObject;
if (!selectObj)
{
Debug.LogError("没有选中任何物体,请选择后再执行操作");
return;
}
//Vector3 center;
var meshFs = Selection.activeTransform.GetComponentsInChildren<MeshFilter>();
var meshRenders = Selection.activeTransform.GetComponentsInChildren<MeshRenderer>();
CombineInstance[] combine = new CombineInstance[meshFs.Length];
var centerPos = GetCenter(meshFs);
Material[] mats= new Material[meshFs.Length];
for (int i = 0; i < meshFs.Length; i++)
{
combine[i].mesh = meshFs[i].sharedMesh;
meshFs[i].transform.position = meshFs[i].transform.position;// - centerPos;
combine[i].transform = meshFs[i].transform.localToWorldMatrix;
mats[i] = meshRenders[i].sharedMaterial;
meshRenders[i].enabled = false;
}
var thisMeshRender = Selection.activeTransform.GetComponent<MeshRenderer>();
thisMeshRender.materials = mats;
var newMesh = new Mesh();
var thisMeshFilter = Selection.activeTransform.GetComponent<MeshFilter>();
// combineMesh 第二个参数 true:合并生成一个大网格; 第二个参数是false:合并生成子网格;
newMesh.CombineMeshes(combine,false);
thisMeshFilter.mesh = newMesh;
}
四.material不同,shader相同,但是贴图不同
这是合并前,合并后的对比:
这里的重点是:
(1)将贴图都存起来
(2)计算uv顶点的个数
(3)将贴图合并,将uv坐标和贴图对应起来!!!!!!
[MenuItem("测试/comebineMesh_DiffMat_CombineTexUv")]
static void CombineMesh_DiffMat_ComTexUV()
{
var selectObj = Selection.activeObject;
if (!selectObj)
{
Debug.LogError("没有选中任何物体,请选择后再执行操作");
return;
}
var meshFs = Selection.activeTransform.GetComponentsInChildren<MeshFilter>();
var meshRenders = Selection.activeTransform.GetComponentsInChildren<MeshRenderer>();
CombineInstance[] combine = new CombineInstance[meshFs.Length];
var centerPos = GetCenter(meshFs);
Texture2D[] textures = new Texture2D[meshFs.Length];
List<Vector2[]> uvList = new List<Vector2[]>();
int uvCount = 0;
Material material;
if (meshRenders.Length>0)
{
material = meshRenders[0]?.sharedMaterial;
}
for (int i = 0; i < meshFs.Length; i++)
{
combine[i].mesh = meshFs[i].sharedMesh;
meshFs[i].transform.position = meshFs[i].transform.position;
combine[i].transform = meshFs[i].transform.localToWorldMatrix;
textures[i] = meshRenders[i].sharedMaterial.GetTexture("_MainTex") as Texture2D;
uvList.Add(meshFs[i].sharedMesh.uv);
uvCount += meshFs[i].sharedMesh.uv.Length;
}
Texture2D tex = new Texture2D(1024, 1024);
Rect[] rects = tex.PackTextures(textures, 0);
Vector2[] uvs = new Vector2[uvCount];
int j = 0;
for (int i = 0; i < meshFs.Length; i++)
{
foreach (var uv in uvList[i])
{
uvs[j].x = Mathf.Lerp(rects[i].xMin, rects[i].xMax, uv.x);
uvs[j].y = Mathf.Lerp(rects[i].yMin, rects[i].yMax, uv.y);
j++;
}
}
var thisMeshRender = Selection.activeTransform.GetComponent<MeshRenderer>();
Material newMat = new Material(meshRenders[0].sharedMaterial.shader);
newMat.CopyPropertiesFromMaterial(meshRenders[0].sharedMaterial);
newMat.SetTexture("_MainTex", tex);
newMat.name = "TestCombine";
var newMesh = new Mesh();
var thisMeshFilter = Selection.activeTransform.GetComponent<MeshFilter>();
newMesh.CombineMeshes(combine,true);
newMesh.uv = uvs;
thisMeshFilter.mesh = newMesh;
thisMeshRender.material = newMat;
}