Unity优化篇——mesh合并

一、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;

扫描二维码关注公众号,回复: 13033735 查看本文章

        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的问题。

         求助各位帮助,当然我这边也会找解决办法。

猜你喜欢

转载自blog.csdn.net/zyxyuting/article/details/105239506