欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity 按区块划分场景模型,并合并网格

程序员文章站 2022-05-31 14:11:14
...

此次项目场景中有相当多的类似小方块的建筑简模(约13w个),每一个都是单独的存在,所以将场景中的所有建筑简模,按照区域划分,并合并网格,减轻了渲染负担,同时按区块合并,方便后续LOD等优化措施。

 [MenuItem("Tool/Combine Mesh With Area")]
    static void CombineMeshWithArea()
    {
        //当前选择的物体,必须为需要合并网格的物体的父物体
        GameObject selectedGo = Selection.activeGameObject;
        MeshFilter[] meshFilters = selectedGo.GetComponentsInChildren<MeshFilter>();
        selectedGo.SetActive(false);
        Transform parent = new GameObject("model").transform;
        parent.position = Vector3.zero;
        //x和z方向上划分的区块个数
        int areaNum_x = 100, areaNum_z = 100;
        //x和z方向的边界坐标
        float min_x=0,min_z=0,max_x=0,max_z = 0;
        //每个区块的长度
        float areaLength_x = 0,areaLength_z = 0;

        Vector3 tempPosition = Vector3.zero;

        Dictionary<string, List<MeshFilter>> areaMeshFilters = new Dictionary<string, List<MeshFilter>>();
        //取到最边界的范围
        for(int i = 0; i < meshFilters.Length; i++)
        {
            tempPosition = meshFilters[i].transform.position;
            max_x = tempPosition.x > max_x ? tempPosition.x : max_x;
            min_x = tempPosition.x < min_x ? tempPosition.x : min_x;
            max_z = tempPosition.z > max_z ? tempPosition.z : max_z;
            min_z = tempPosition.z < min_z ? tempPosition.z : min_z;
        }
        areaLength_x = (max_x - min_x)/ areaNum_x;
        areaLength_z = (max_z - min_z)/ areaNum_z;

        //将所有物体划分至对应的区块中
        for (int i = 0; i < meshFilters.Length; i++)
        {
            int tempX = (int)((meshFilters[i].transform.position.x - min_x) / areaLength_x);
            int tempZ = (int)((meshFilters[i].transform.position.z - min_z) / areaLength_z);

            string key = tempX + "," + tempZ;
            if (areaMeshFilters.ContainsKey(key))
            {
                areaMeshFilters[key].Add(meshFilters[i]);
            }
            else
            {
                List<MeshFilter> tempFilterList = new List<MeshFilter>();
                tempFilterList.Add(meshFilters[i]);
                areaMeshFilters.Add(key, tempFilterList);
            }
        }
        Debug.Log(areaMeshFilters.Count);
        //遍历所有区块,并合并网格
        foreach (string item in areaMeshFilters.Keys)
        {
            List<MeshFilter> value = areaMeshFilters[item];
            CombineInstance[] combineInstances = new CombineInstance[value.Count];
            for (int i = 0; i < value.Count; i++)
            {
                combineInstances[i].mesh = value[i].sharedMesh;
                combineInstances[i].transform = value[i].transform.localToWorldMatrix;
            }

            //新网格对象
            Mesh tempNewMesh = new Mesh();
            tempNewMesh.name = item;
            //将combineInstances数组传入函数
            tempNewMesh.CombineMeshes(combineInstances);
            //给当前空物体,添加网格组件;将合并后的网格,给到自身网格
            GameObject tempGo = new GameObject(item);
            tempGo.transform.parent = parent;
            tempGo.gameObject.AddComponent<MeshFilter>().sharedMesh = tempNewMesh;
            //附材质;       
            tempGo.gameObject.AddComponent<MeshRenderer>().sharedMaterial = Resources.Load<Material>("Materials/FrontCol");
        }
    }

完成后的效果:   

Unity 按区块划分场景模型,并合并网格

合并完成后,可以设置合并后的网格中心点到模型中心,具体见:https://blog.csdn.net/weixin_39562801/article/details/107842345