鼠标点击高亮Mesh三角形功能失效排查
问题:鼠标点击Mesh三角形无法修改颜色(Debug线正常)
使用legacy VertexLit shader创建了24个顶点的立方体Mesh,点击三角形时Debug线能正确高亮目标区域,但Mesh颜色无法改变。相关代码如下:
点击处理代码
void HighlightTriangle2() { if (!Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit)) { return; } MeshCollider meshCollider = hit.collider as MeshCollider; if (meshCollider == null || meshCollider.sharedMesh == null) { return; } Debug.Log("hit.triangleIndex = " + hit.triangleIndex); mf.mesh = meshCollider.sharedMesh; Vector3[] vertices = mf.mesh.vertices; int[] triangles = mf.mesh.triangles; Vector3 p0 = vertices[triangles[hit.triangleIndex * 3 + 0]]; Vector3 p1 = vertices[triangles[hit.triangleIndex * 3 + 1]]; Vector3 p2 = vertices[triangles[hit.triangleIndex * 3 + 2]]; Transform hitTransform = hit.collider.transform; p0 = hitTransform.TransformPoint(p0); p1 = hitTransform.TransformPoint(p1); p2 = hitTransform.TransformPoint(p2); //Debug.DrawLine(p0, p1, lineColor, duration); //Debug.DrawLine(p1, p2, lineColor, duration); //Debug.DrawLine(p2, p0, lineColor, duration); int v1 = hit.triangleIndex * 3 + 0; int v2 = hit.triangleIndex * 3 + 1; int v3 = hit.triangleIndex * 3 + 2; colorArray[v1] = Color.red; colorArray[v2] = Color.red; colorArray[v3] = Color.red; mf.mesh.colors = colorArray; }
Mesh创建代码
private void CreateMesh() { Mesh mesh = new Mesh(); mesh.Clear(); List<Vector3> vertList = DoVertices(); mesh.SetVertices(vertList); List<int> trisList = DoTriangles(vertList); mesh.SetTriangles(trisList, 0); List<Vector2> uvsList = DoUVs_TEST(); mesh.uv = uvsList.ToArray(); MeshRenderer mr = GetComponent<MeshRenderer>(); mr.material = defaultMaterial; Color[] colorArray = new Color[mesh.vertices.Length]; for (int k = 0; k < mesh.vertices.Length; k++) { colorArray[k] = Color.white; } mesh.colors = colorArray; mf.mesh = mesh; }
问题原因及修复方案
1. 错误操作SharedMesh
代码中mf.mesh = meshCollider.sharedMesh;直接将MeshFilter的Mesh替换为碰撞体的共享Mesh,这不仅会影响所有使用该共享Mesh的对象,还会导致后续修改的是只读的共享Mesh(无法保存修改)。应该直接操作当前MeshFilter自身的Mesh。
2. 顶点索引获取错误
你错误地将三角形索引的偏移值当作顶点索引:
int v1 = hit.triangleIndex * 3 + 0;
正确的做法是从triangles数组中取出当前三角形对应的三个顶点索引——triangles数组存储的是每个三角形的顶点索引序列,第N个三角形的三个顶点索引是triangles[N*3]、triangles[N*3+1]、triangles[N*3+2]。
3. Color数组作用域问题
CreateMesh中的colorArray是局部变量,若HighlightTriangle2中的colorArray是成员变量,需要确保它始终与当前Mesh的顶点数量匹配,并且每次修改前正确引用当前Mesh的颜色数组(或维护一份同步的数组)。
修正后的代码
// 确保colorArray是类成员变量,在CreateMesh时初始化 private Color[] colorArray; void HighlightTriangle2() { if (!Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit)) { return; } MeshCollider meshCollider = hit.collider as MeshCollider; if (meshCollider == null || meshCollider.sharedMesh == null) { return; } Debug.Log("hit.triangleIndex = " + hit.triangleIndex); // 直接操作当前MeshFilter的Mesh,而非sharedMesh Mesh mesh = mf.mesh; int[] triangles = mesh.triangles; // 获取当前三角形对应的三个顶点索引 int idx0 = triangles[hit.triangleIndex * 3]; int idx1 = triangles[hit.triangleIndex * 3 + 1]; int idx2 = triangles[hit.triangleIndex * 3 + 2]; // 可选:重置颜色数组为白色,只高亮当前点击的三角形 // Array.Fill(colorArray, Color.white); // 修改对应顶点的颜色 colorArray[idx0] = Color.red; colorArray[idx1] = Color.red; colorArray[idx2] = Color.red; // 将修改后的颜色数组赋值给Mesh mesh.colors = colorArray; // 标记Mesh需要更新,确保Unity识别到修改 mesh.RecalculateBounds(); } private void CreateMesh() { Mesh mesh = new Mesh(); mesh.Clear(); List<Vector3> vertList = DoVertices(); mesh.SetVertices(vertList); List<int> trisList = DoTriangles(vertList); mesh.SetTriangles(trisList, 0); List<Vector2> uvsList = DoUVs_TEST(); mesh.uv = uvsList.ToArray(); MeshRenderer mr = GetComponent<MeshRenderer>(); mr.material = defaultMaterial; // 初始化类成员的colorArray colorArray = new Color[mesh.vertices.Length]; for (int k = 0; k < mesh.vertices.Length; k++) { colorArray[k] = Color.white; } mesh.colors = colorArray; mf.mesh = mesh; }
额外检查项
- 确认你的
VertexLitshader支持顶点颜色:legacy的Standard VertexLitshader默认支持,但如果是自定义shader,需要确保在顶点着色器中读取COLOR语义,并将其传递给片元着色器使用。 - 确保MeshCollider的
convex选项未勾选(除非必要),避免影响三角形索引的检测。
内容的提问来源于stack exchange,提问作者kbdev
相关产品推荐
相关产品推荐

