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

此次项目场景中有相当多的类似小方块的建筑简模(约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");
        }
    }

完成后的效果:   

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值