美文网首页程序员
[Unity] 动态合并和拆分 mesh 和 贴图

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

作者: 胡海辉 | 来源:发表于2020-07-01 22:08 被阅读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;

                  }

                }

            }

        }

    ```

    相关文章

      网友评论

        本文标题:[Unity] 动态合并和拆分 mesh 和 贴图

        本文链接:https://www.haomeiwen.com/subject/tjlkqktx.html