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");
}
}
完成后的效果:
合并完成后,可以设置合并后的网格中心点到模型中心,具体见:https://blog.csdn.net/weixin_39562801/article/details/107842345
下一篇: Js实现简单的表单验证(小白篇)