Unity程序化地形生成数组越界报错及碰撞体添加问题求助
报错原因及修复方案
1. IndexOutOfRangeException 数组越界错误
IndexOutOfRangeException: Index was outside the bounds of the array. mapgeneration.CreateShape () (at Assets/mapgeneration.cs:108
mapgeneration.Update () (at Assets/mapgeneration.cs:131)
错误根源
你在遍历顶点时的索引操作顺序错误:
vertices[iloopedforvertecy] = new Vector3(x, y, z); iloopedforvertecy += 1; // 索引先自增 colors[iloopedforvertecy] = gradient.Evaluate(height); // 用自增后的索引访问数组,最后一次会超出边界
同时存在两个逻辑错误:
- 渐变采样的归一化高度值固定写死为0.5f,没有使用当前顶点的实际高度,渐变着色不会生效
- 遍历顶点的同时统计高度极值,此时计算的归一化高度没有基于完整的地形高度范围,结果不准确
修复后的CreateShape代码
void CreateShape() { vertices = new Vector3[(xsize + 1) * (zsize + 1)]; water.transform.localScale = new Vector3(xsize, 0, zsize); int iloopedforvertecy = 0; triangles = new int[xsize * zsize * 6]; int vert = 0; int tris = 0; for(int z = 0; z < zsize; z++) { for(int x = 0; x < xsize; x++) { triangles[tris + 0] = vert + 0; triangles[tris + 1] = vert + xsize + 1; triangles[tris + 2] = vert + 1; triangles[tris + 3] = vert + 1; triangles[tris + 4] = vert + xsize + 1; triangles[tris + 5] = vert + xsize + 2; vert++; tris += 6; } vert++; } // 第一次遍历:生成顶点,统计高度极值 minterainheight = float.MaxValue; maxterainheight = float.MinValue; for (int z = 0; z <= zsize; z++) { for(int x = 0; x <= xsize; x++) { float xCoord = (float)x / xsize * scale + xoffset; float zCoord = (float)z / zsize * scale + zoffset; float y = Mathf.PerlinNoise(xCoord * smooth, zCoord * smooth) * smoothfactor; vertices[iloopedforvertecy] = new Vector3(x, y, z); iloopedforvertecy += 1; if(y > maxterainheight) { maxterainheight = y; } if(y < minterainheight) { minterainheight = y; } } } // 第二次遍历:计算顶点颜色,此时高度范围已经确定 colors = new Color[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { float height = Mathf.InverseLerp(minterainheight, maxterainheight, vertices[i].y); colors[i] = gradient.Evaluate(height); } }
2. 地形碰撞体添加方案
操作步骤非常简单:
- 把类头部的特性修改为:
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider))],确保物体自动挂载所需组件 - 修改
UpdateMsh方法,刷新网格后同步更新碰撞体的网格数据:
void UpdateMsh() { mesh.Clear(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.RecalculateNormals(); mesh.colors = colors; // 同步碰撞体网格 GetComponent<MeshCollider>().sharedMesh = mesh; }
另外注意:你当前把CreateShape和UpdateMsh放在Update中每帧执行,性能开销很高,如果不需要实时修改地形参数刷新地形,建议把这两行调用从Update中删除,仅保留Start中的调用即可。
内容的提问来源于stack exchange,提问作者BlackBeltEast
相关产品推荐
相关产品推荐

