You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 00:36:05