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

绘制三角形时触发UV索引越界异常的原因及解决咨询

UV索引越界异常排查与修复(Unity Mesh生成场景)

嘿,我之前也碰到过一模一样的情况——明明三角形能正常显示,但控制台偏要蹦出UV索引越界的警告,别提有多闹心了!咱们来一步步拆解问题,找到解决办法。

问题根源分析

从你贴的代码来看,你直接复制了预制体Mesh的顶点、UV和三角形索引数据,但触发越界警告的核心原因只有一个:三角形数组里的某个索引值,超出了UV数组的长度范围。

虽然Mesh能正常显示,大概率是顶点数组和三角形索引是匹配的,但UV数组的长度没跟上,导致Unity在尝试给顶点对应UV时找不到对应的数据。

第一步:先排查数据合法性

在你的Start方法里加几行日志,先搞清楚三个数组的长度和三角形索引的最大值:

void Start() {
    Mesh prefabMesh = meshPrefab.GetComponent<MeshFilter>().sharedMesh;
    newVertices = prefabMesh.vertices;
    newUV = prefabMesh.uv;
    newTriangles = prefabMesh.triangles;

    // 打印数组长度
    Debug.Log($"顶点数:{newVertices.Length},UV数:{newUV.Length}");
    // 找三角形索引的最大值
    int maxIndex = -1;
    foreach(int idx in newTriangles) {
        if(idx > maxIndex) maxIndex = idx;
    }
    Debug.Log($"三角形最大索引:{maxIndex}");

    // 剩下的代码...
}

运行后看控制台:

  • 如果UV数 < 顶点数:说明预制体的Mesh本身UV数据不完整,或者你后续修改了顶点数组但没同步更新UV
  • 如果三角形最大索引 >= UV数:这就是直接触发越界的原因

针对性修复方案

情况1:预制体Mesh数据异常

如果日志显示UV数组长度比顶点短,大概率是预制体的Mesh在编辑器里损坏了,或者导出时UV通道没正确生成。这时候可以:

  • 重新创建预制体的Mesh,或者从建模软件重新导出
  • 手动补全UV数组,比如给缺失的UV赋值默认值Vector2.zero:
if(newUV.Length < newVertices.Length) {
    Vector2[] fixedUV = new Vector2[newVertices.Length];
    System.Array.Copy(newUV, fixedUV, newUV.Length);
    for(int i = newUV.Length; i < fixedUV.Length; i++) {
        fixedUV[i] = Vector2.zero;
    }
    newUV = fixedUV;
}

情况2:后续代码修改了数组长度

如果你在创建新Mesh前,修改了newVertices或newUV的长度(比如添加了新顶点但忘了加UV),那必须保证newUV.Length == newVertices.Length,同时所有三角形索引都要小于这个长度。

情况3:完整的正确代码示例

这里补全你没写完的代码,同时加入数据校验和修复逻辑:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MeshGenerator : MonoBehaviour {
    public GameObject meshPrefab;
    public Vector3[] newVertices;
    public Vector2[] newUV;
    public int[] newTriangles;
    private Mesh mesh;

    void Start() {
        Mesh prefabMesh = meshPrefab.GetComponent<MeshFilter>().sharedMesh;
        // 完整复制数据(用Clone避免直接修改预制体的共享Mesh)
        newVertices = prefabMesh.vertices.Clone() as Vector3[];
        newUV = prefabMesh.uv.Clone() as Vector2[];
        newTriangles = prefabMesh.triangles.Clone() as int[];

        // 数据校验与修复
        if(newUV.Length != newVertices.Length) {
            Debug.LogWarning("UV数组与顶点数组长度不匹配,自动修复");
            Vector2[] fixedUV = new Vector2[newVertices.Length];
            System.Array.Copy(newUV, fixedUV, newUV.Length);
            // 给缺失的UV赋值默认值
            for(int i = newUV.Length; i < fixedUV.Length; i++) {
                fixedUV[i] = Vector2.zero;
            }
            newUV = fixedUV;
        }

        int maxTriangleIndex = newTriangles.Length > 0 ? newTriangles.Max() : -1;
        if(maxTriangleIndex >= newVertices.Length) {
            Debug.LogError("三角形索引超出顶点数组范围,请检查预制体Mesh或修改后的顶点数据");
            return;
        }

        // 创建并配置新Mesh
        mesh = new Mesh();
        mesh.vertices = newVertices;
        mesh.uv = newUV;
        mesh.triangles = newTriangles;
        // 别忘了更新法线和包围盒
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        // 将新Mesh赋值给当前物体
        MeshFilter mf = GetComponent<MeshFilter>() ?? gameObject.AddComponent<MeshFilter>();
        mf.mesh = mesh;

        // 复制预制体的材质(可选)
        MeshRenderer mr = GetComponent<MeshRenderer>() ?? gameObject.AddComponent<MeshRenderer>();
        mr.material = meshPrefab.GetComponent<MeshRenderer>().sharedMaterial;
    }
}

最后提醒

Unity的Mesh要求顶点、UV、法线等数组的长度必须完全一致,每个索引对应的各个通道数据都要存在,哪怕是默认值。所以只要保证这一点,索引越界的问题就不会再出现啦。

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:55:45