[Unity] 动态合并和拆分 mesh 和 贴图

当场景中有很多不同的模型和贴图时,会导致Batch 会很高,所以我们可以去合并这些小物件模型和贴图,已达到省资源的目的。

首先在记录每一个需要被动态合并的物的material,mesh, texture,uv 等信息

 public void CollectSmallObject(SmallObject mSmallobject)
 {
        ObjectData data = default(ObjectData);
        data.objId = mSmallobject.objId;
        render = mSmallobject.GetComponentsInChildren();
        mesh = mSmallobject.GetComponentsInChildren();

        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;
              }
            }
        }
    }

你可能感兴趣的:(Unity,优化,unity)