一、mesh合并大体分为:
1.合并网格
2.合并贴图
3.附加材质
4.重新计算UV
这里提一下附加材质,附加材质是对合并后的mesh重新赋予了一个material。废话不多说上代码!
备注:代码大多是整合的网上的资源,而且代码未优化!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CombineMesh : MonoBehaviour
{
public Material combMat;//合并后赋予新mesh 的材质
public GameObject[] needCombMeshAry;//需要合并的对象
void Start()
{
OrdinaryCombine();
}
private void OrdinaryCombine()
{
float startTime = Time.realtimeSinceStartup;
List<CombineInstance> combineInstance = new List<CombineInstance>();
List<Texture2D> textures = new List<Texture2D>();
List<Vector2[]> uvList = new List<Vector2[]>();
int uvCount = 0;
int width = 0;
int height = 0;
for (int i = 0; i<needCombMeshAry.Length; ++i) {
MeshRenderer renderer = needCombMeshAry[i].GetComponent<MeshRenderer>();
MeshFilter filter = needCombMeshAry[i].GetComponent<MeshFilter>();
for (int k = 0; k< filter.sharedMesh.subMeshCount; ++k) {
CombineInstance ci = new CombineInstance();
ci.mesh = filter.sharedMesh;
ci.subMeshIndex = k;
// 拿父节点的本地坐标*合并进来物体的世界坐标,得到合并进来物体相对父节点的偏移位置
ci.transform = transform.worldToLocalMatrix * filter.transform.localToWorldMatrix;
combineInstance.Add(ci);
}
uvList.Add(filter.sharedMesh.uv);
uvCount += filter.sharedMesh.uv.Length;
if (renderer.sharedMaterial.mainTexture != null) {
textures.Add(renderer.sharedMaterial.mainTexture as Texture2D);
width += renderer.sharedMaterial.mainTexture.width;
height += renderer.sharedMaterial.mainTexture.height;
}
}
// 给合并的目标物体添加MeshRenderer和MeshFilter
MeshRenderer tempRender = GetComponent<MeshRenderer>();
if (!tempRender)
{
tempRender = gameObject.AddComponent<MeshRenderer>();
}
MeshFilter tempFilter = GetComponent<MeshFilter>();
if (!tempFilter)
{
tempFilter = gameObject.AddComponent<MeshFilter>();
}
tempFilter.mesh = new Mesh();
// 合并网格,设置新材质
tempFilter.mesh.CombineMeshes(combineInstance.ToArray(), true, true);
tempRender.material = combMat;
// 将多个纹理放到一个集合包里面
Texture2D meshAtlas = new Texture2D(get2Pow(width), get2Pow(height));
Rect[] packingResult = meshAtlas.PackTextures(textures.ToArray(), 0);
Vector2[] atlasUVs = new Vector2[uvCount];
// 重新计算UV
int counter = 0;
for (int index = 0; index < uvList.Count; ++index)
{
foreach (Vector2 uv in uvList[index])
{
atlasUVs[counter].x = Mathf.Lerp(packingResult[index].xMin, packingResult[index].xMax, uv.x);
atlasUVs[counter].y = Mathf.Lerp(packingResult[index].yMin, packingResult[index].yMax, uv.y);
counter++;
}
}
// 设置贴图和UV
tempRender.material.mainTexture = meshAtlas;
tempFilter.mesh.uv = atlasUVs;
Debug.Log("合并耗时 : " + (Time.realtimeSinceStartup - startTime) * 1000 + " ms");
}
private int get2Pow(int into) // 贴图最大不超过2的10次方,1024*1024
{
int outo = 1;
for (int i = 0; i<10; ++i) {
outo *= 2;
if (outo > into) {
break;
}
}
return outo;
}
}
二、问题
在上述中,mesh合并没有什么问题。但我观察合并后的mesh时,发现有明显的切割边缘。直接上图如下:箭头指向部分就是合并后的mesh,几个凸多边形合并出来的都有类似这种问题。我这里猜测是不是模型边缘uv的问题。
求助各位帮助,当然我这边也会找解决办法。