为何自定义网格放入MeshCollider后显示为盒状碰撞体?
问题:MeshCollider显示为3D盒状而非预期平面网格
我在Unity中实现按住鼠标左键绘制UI选择框,将其投影到世界空间的MeshCollider以检测框选物体。通过RaycastAll将选择框四个角的屏幕坐标转换为世界坐标(这部分功能正常),但生成的MeshCollider显示为3D盒状,而非预期的4顶点平面网格。Inspector显示已加载自定义网格,双击网格能看到预期的平面,但场景中碰撞体显示为8顶点盒状。
主脚本代码
////////// SELECTION BOX //////////////// //set vertex p0 to the position where the player first clicked if (Input.GetMouseButtonDown(0)) { clickPos = Input.mousePosition; RaycastHit[] hits0 = Physics.RaycastAll(Camera.main.ScreenPointToRay(clickPos)); foreach (RaycastHit hit in hits0) { if (hit.collider.tag == "chunk") { p0 = new Vector3(hit.point.x, -2f, hit.point.z); } } } //everything disappear if player let go the mouse button if (Input.GetMouseButtonUp(0)) { selectionBox.gameObject.SetActive(false); GetComponent<MeshCollider>().sharedMesh?.Clear(); GetComponent<MeshCollider>().enabled = false; } //if mouse button is held down, the UI box appear and the other vertices(p1, p2, p3) are determined accordingly if (Input.GetMouseButton(0)) { mousePos = Input.mousePosition; if ((clickPos - mousePos).magnitude > 20f) { // selection box UI selectionBox.gameObject.SetActive(true); selectionBox.rectTransform.sizeDelta = new Vector2(Mathf.Abs(clickPos.x - mousePos.x), Mathf.Abs(clickPos.y - mousePos.y)); selectionBox.rectTransform.anchoredPosition = clickPos + new Vector3((mousePos.x - clickPos.x) / 2, (mousePos.y - clickPos.y) / 2, 0f); //selection box meshcollider RaycastHit[] hits1 = Physics.RaycastAll(Camera.main.ScreenPointToRay(mousePos)); foreach (RaycastHit hit in hits1) { if (hit.collider.tag == "chunk") { p1 = new Vector3(hit.point.x, -2f, hit.point.z); } } RaycastHit[] hits2 = Physics.RaycastAll(Camera.main.ScreenPointToRay(new Vector2(clickPos.x, mousePos.y))); foreach (RaycastHit hit in hits2) { if (hit.collider.tag == "chunk") { p2 = new Vector3(hit.point.x, -2f, hit.point.z); } } RaycastHit[] hits3 = Physics.RaycastAll(Camera.main.ScreenPointToRay(new Vector2(mousePos.x, clickPos.y))); foreach (RaycastHit hit in hits3) { if (hit.collider.tag == "chunk") { p3 = new Vector3(hit.point.x, -2f, hit.point.z); } } //meshGen is a custom class that takes in four Vector3 and output the corresponding mesh, then the mesh is added to the meshcollider. mesh = meshGen.GenerateMeshFromWorldPoint(p0, p1, p2, p3); GetComponent<MeshCollider>().sharedMesh = mesh; GetComponent<MeshCollider>().convex = true; GetComponent<MeshCollider>().enabled = true; } }
MeshGen类代码
public class MeshGen { Vector3[] _vertices; int[] _triangles; public Mesh GenerateMeshFromWorldPoint(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) { _vertices = new Vector3[] { p0, p1, p2, p3 }; _triangles = new int[] { 0, 1, 2, 0, 3, 1 }; Mesh mesh = new Mesh(); mesh.name = "Custom Mesh Collider"; mesh.vertices = _vertices; mesh.triangles = _triangles; return mesh; } }
解决思路
- 关闭Convex选项:核心原因是开启了MeshCollider的
convex = true,Unity为了让凸碰撞体满足封闭体积要求,会自动将平面网格拉伸为薄盒状。直接移除GetComponent<MeshCollider>().convex = true代码,或设置为false即可恢复平面碰撞体。 - 完善Mesh数据:虽然不影响碰撞功能,但补充法线和UV可让网格更规范,避免潜在显示问题:
在MeshGen的GenerateMeshFromWorldPoint方法中添加:// 添加统一向上的法线,匹配平面朝向 mesh.normals = new Vector3[] { Vector3.up, Vector3.up, Vector3.up, Vector3.up }; // 添加UV坐标 mesh.uv = new Vector2[] { Vector2.zero, Vector2.right, Vector2.up, Vector2.one }; - 优化Mesh清理逻辑:当前
sharedMesh?.Clear()可能损坏Mesh资源,建议改为直接赋值null:GetComponent<MeshCollider>().sharedMesh = null; - 检查物体变换参数:确保承载MeshCollider的GameObject没有非均匀缩放或异常偏移,避免网格被扭曲显示。
内容的提问来源于stack exchange,提问作者MathMith
相关产品推荐
相关产品推荐

