程序员

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

2020-07-01  本文已影响0人  胡海辉

当场景中有很多不同的模型和贴图时,会导致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;

              }

            }

        }

    }

```

上一篇下一篇

猜你喜欢

热点阅读