当场景中有很多不同的模型和贴图时,会导致Batch 会很高,所以我们可以去合并这些小物件模型和贴图,已达到省资源的目的。
首先在记录每一个需要被动态合并的物的material,mesh, texture,uv 等信息
public void CollectSmallObject(SmallObject mSmallobject)
{
ObjectData data = default(ObjectData);
data.objId = mSmallobject.objId;
render = mSmallobject.GetComponentsInChildren<MeshRenderer>();
mesh = mSmallobject.GetComponentsInChildren<MeshFilter>();
data.MaterialData = new MaterialData[mesh.Length];
MaterialData materialData = default(RoomMaterialData);
for (int i = 0; i < mesh.Length && i < render.Length; i++)
{
materialData.mainTexture = render[i].sharedMaterial.mainTexture;
materialData.uv = mesh[i].mesh.uv;
materialData.render = render[i];
materialData.mesh = mesh[i];
data.MaterialData[i] = materialData;
}
//深沉次遍历
CollectSmallObject(roomType, ref data);
}
然后在适当的时间调合并代码
private void CombineSmallObjectTexture()
{
// 清除缓存内数据
uvList.Clear();
textures.Clear();
objectDatas.Clear();
// 创建一个新的材质球
Material smallObjectMaterial = new Material(Shader.Find("Unilt/Texture"));
// 或者所有需要合并的物体数据
foreach (ObjectData objectData in _SmallobjectDataList)
{
MaterialData data = default(MaterialData);
for (int i = 0; i < objectData.MaterialData.Length; i++)
{
data = objectData.MaterialData[i];
uvList.Add(data.uv);
textures.Add(data.mainTexture as Texture2D);
objectDatas.Add(data);
}
}
// 合并所有的贴图
packingResult = meshAtlas.PackTextures(textures.ToArray(), 0, 1024, true);
smallObjectMaterial.mainTexture = meshAtlas;
// 合并UV
Vector2[] atlasUVs;
for (int i = 0; i < uvList.Count; i++)
{
int j = 0;
atlasUVs = new Vector2[uvList[i].Length];
foreach (Vector2 uv in uvList[i])
{
atlasUVs[j].x = Mathf.Lerp(packingResult[i].xMin, packingResult[i].xMax, uv.x);
atlasUVs[j].y = Mathf.Lerp(packingResult[i].yMin, packingResult[i].yMax, uv.y);
j++;
}
//材质球替换
objectDatas[i].render.material = smallObjectMaterial;
// uv 替换
objectDatas[i].mesh.sharedMesh.uv = atlasUVs;
}
}
用sharedMesh 是因为,shareMesh是当前正在使用的mesh,如果直接修改mesh,他会先动态创建一个mesh,在修改
如果你想把合并的内容在拆开,那之前我们最开始缓存的自己的材质球信息就大作用了。
private void RestOneSmallObjectMaterial(SmallObject mSmallobject, ref RoomObjectData mRoomObjectData)
{
foreach (ObjectData objectData in _SmallobjectDataList)
{
MaterialData data = default(MaterialData);
for (int i = 0; i < objectData.MaterialData.Length; i++)
{
if (mSmallobject.objId == objectData.objId)
{
data = objectData.MaterialData[i];
if (data.mesh == null) continue;
data.mesh.sharedMesh.uv = data.uv;
data.render.material.mainTexture = data.mainTexture;
}
}
}
}