152 lines
4.3 KiB
C#
152 lines
4.3 KiB
C#
using UnityEngine;
|
||
using System.Collections.Generic;
|
||
|
||
[RequireComponent(typeof(MeshCollider))]
|
||
public class MeshColliderGizmo : MonoBehaviour
|
||
{
|
||
[Tooltip("Gizmo显示颜色")]
|
||
public Color lineColor = new Color(0, 1, 1, 0.8f);
|
||
|
||
[Tooltip("线框宽度")]
|
||
public float lineWidth = 1.0f;
|
||
|
||
[Tooltip("是否在运行时显示")]
|
||
public bool showInPlayMode = true;
|
||
|
||
[Tooltip("是否只显示边缘")]
|
||
public bool showEdgesOnly = true;
|
||
|
||
private MeshCollider _meshCollider;
|
||
private Mesh _mesh;
|
||
private List<Vector3> _vertices = new List<Vector3>();
|
||
private List<int> _triangles = new List<int>();
|
||
private List<Vector3> _linePoints = new List<Vector3>();
|
||
private Material _glMaterial;
|
||
private Matrix4x4 _localToWorldMatrix;
|
||
|
||
private void Awake()
|
||
{
|
||
_meshCollider = GetComponent<MeshCollider>();
|
||
InitializeMeshData();
|
||
InitializeGLMaterial();
|
||
}
|
||
|
||
private void InitializeMeshData()
|
||
{
|
||
// 尝试获取网格数据
|
||
MeshFilter meshFilter = GetComponent<MeshFilter>();
|
||
if (meshFilter != null && meshFilter.sharedMesh != null)
|
||
{
|
||
_mesh = meshFilter.sharedMesh;
|
||
}
|
||
else if (_meshCollider.sharedMesh != null)
|
||
{
|
||
_mesh = _meshCollider.sharedMesh;
|
||
}
|
||
|
||
if (_mesh != null)
|
||
{
|
||
_vertices.Clear();
|
||
_triangles.Clear();
|
||
_mesh.GetVertices(_vertices);
|
||
_mesh.GetTriangles(_triangles, 0);
|
||
GenerateLinePoints();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("未找到有效的Mesh资源", this);
|
||
}
|
||
}
|
||
|
||
private void InitializeGLMaterial()
|
||
{
|
||
// 创建用于GL绘制的材质
|
||
_glMaterial = new Material(Shader.Find("Hidden/Internal-Colored"));
|
||
_glMaterial.hideFlags = HideFlags.HideAndDontSave;
|
||
_glMaterial.SetInt("ZWrite", 0);
|
||
_glMaterial.SetInt("ZTest", (int)UnityEngine.Rendering.CompareFunction.Always);
|
||
}
|
||
|
||
private void GenerateLinePoints()
|
||
{
|
||
if (showEdgesOnly)
|
||
{
|
||
// 只显示边缘线(去重处理)
|
||
HashSet<long> edgeSet = new HashSet<long>();
|
||
_linePoints.Clear();
|
||
|
||
for (int i = 0; i < _triangles.Count; i += 3)
|
||
{
|
||
AddEdge(_triangles[i], _triangles[i + 1], edgeSet);
|
||
AddEdge(_triangles[i + 1], _triangles[i + 2], edgeSet);
|
||
AddEdge(_triangles[i + 2], _triangles[i], edgeSet);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 显示所有三角形线
|
||
_linePoints.Clear();
|
||
for (int i = 0; i < _triangles.Count; i += 3)
|
||
{
|
||
_linePoints.Add(_vertices[_triangles[i]]);
|
||
_linePoints.Add(_vertices[_triangles[i + 1]]);
|
||
_linePoints.Add(_vertices[_triangles[i + 1]]);
|
||
_linePoints.Add(_vertices[_triangles[i + 2]]);
|
||
_linePoints.Add(_vertices[_triangles[i + 2]]);
|
||
_linePoints.Add(_vertices[_triangles[i]]);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void AddEdge(int v1, int v2, HashSet<long> edgeSet)
|
||
{
|
||
// 创建唯一的边ID,避免重复
|
||
long edgeId = (long)Mathf.Min(v1, v2) << 32 | Mathf.Max(v1, v2);
|
||
if (edgeSet.Contains(edgeId)) return;
|
||
|
||
edgeSet.Add(edgeId);
|
||
_linePoints.Add(_vertices[v1]);
|
||
_linePoints.Add(_vertices[v2]);
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
_localToWorldMatrix = transform.localToWorldMatrix;
|
||
}
|
||
|
||
private void OnRenderObject()
|
||
{
|
||
if (!showInPlayMode || _mesh == null || _linePoints.Count == 0 || _glMaterial == null)
|
||
return;
|
||
|
||
// 设置材质和颜色
|
||
_glMaterial.SetPass(0);
|
||
GL.PushMatrix();
|
||
GL.MultMatrix(_localToWorldMatrix);
|
||
GL.Color(lineColor);
|
||
|
||
// 设置线宽
|
||
GL.Begin(GL.LINES);
|
||
for (int i = 0; i < _linePoints.Count; i++)
|
||
{
|
||
GL.Vertex(_linePoints[i]);
|
||
}
|
||
GL.End();
|
||
|
||
GL.PopMatrix();
|
||
}
|
||
|
||
// 编辑器下的Gizmo预览
|
||
#if UNITY_EDITOR
|
||
private void OnDrawGizmos()
|
||
{
|
||
if (!Application.isPlaying && _mesh != null)
|
||
{
|
||
Gizmos.color = lineColor;
|
||
Gizmos.matrix = transform.localToWorldMatrix;
|
||
Gizmos.DrawWireMesh(_mesh);
|
||
}
|
||
}
|
||
#endif
|
||
}
|