using UnityEditor; using UnityEngine; [RequireComponent(typeof(CapsuleCollider))] public class CapsuleColliderGizmo : MonoBehaviour { [Tooltip("Gizmo显示颜色")] public Color gizmoColor = new Color(0, 1, 0, 0.3f); [Tooltip("是否始终显示Gizmo")] public bool alwaysShow = true; private CapsuleCollider capsuleCollider; private void Awake() { capsuleCollider = GetComponent(); } private void OnDrawGizmos() { # if UNITY_EDITOR if (!alwaysShow && !Selection.Contains(gameObject)) return; #endif DrawCapsuleGizmo(); } private void OnDrawGizmosSelected() { if (alwaysShow) return; DrawCapsuleGizmo(); } private void DrawCapsuleGizmo() { if (capsuleCollider == null) { capsuleCollider = GetComponent(); if (capsuleCollider == null) return; } Gizmos.color = gizmoColor; // 获取胶囊体的参数 Vector3 center = transform.TransformPoint(capsuleCollider.center); float radius = capsuleCollider.radius * Mathf.Max(transform.lossyScale.x, transform.lossyScale.z); float height = capsuleCollider.height * transform.lossyScale.y; int direction = capsuleCollider.direction; // 计算胶囊体的两个半球中心 Vector3 halfHeight = Vector3.zero; switch (direction) { case 0: // X轴 halfHeight = Vector3.right * (height / 2 - radius); radius = capsuleCollider.radius * Mathf.Max(transform.lossyScale.y, transform.lossyScale.z); break; case 1: // Y轴 halfHeight = Vector3.up * (height / 2 - radius); radius = capsuleCollider.radius * Mathf.Max(transform.lossyScale.x, transform.lossyScale.z); break; case 2: // Z轴 halfHeight = Vector3.forward * (height / 2 - radius); radius = capsuleCollider.radius * Mathf.Max(transform.lossyScale.x, transform.lossyScale.y); break; } Vector3 topCenter = center + halfHeight; Vector3 bottomCenter = center - halfHeight; // 绘制胶囊体的圆柱部分 if (height > radius * 2) { DrawCylinder(topCenter, bottomCenter, radius, 16); } // 绘制上下两个半球 Gizmos.DrawSphere(topCenter, radius); Gizmos.DrawSphere(bottomCenter, radius); } // 添加自定义圆柱绘制方法 private void DrawCylinder(Vector3 topCenter, Vector3 bottomCenter, float radius, int segments) { Vector3 up = (topCenter - bottomCenter).normalized; Vector3 right = Vector3.Cross(up, Vector3.forward).normalized; if (right.sqrMagnitude < 0.01f) right = Vector3.Cross(up, Vector3.right).normalized; Vector3 forward = Vector3.Cross(up, right).normalized; for (int i = 0; i < segments; i++) { float angle = (i / (float)segments) * Mathf.PI * 2; float nextAngle = ((i + 1) / (float)segments) * Mathf.PI * 2; Vector3 topPoint = topCenter + (Mathf.Cos(angle) * right + Mathf.Sin(angle) * forward) * radius; Vector3 topNextPoint = topCenter + (Mathf.Cos(nextAngle) * right + Mathf.Sin(nextAngle) * forward) * radius; Vector3 bottomPoint = bottomCenter + (Mathf.Cos(angle) * right + Mathf.Sin(angle) * forward) * radius; Vector3 bottomNextPoint = bottomCenter + (Mathf.Cos(nextAngle) * right + Mathf.Sin(nextAngle) * forward) * radius; // 绘制侧面竖线 Gizmos.DrawLine(topPoint, bottomPoint); // 绘制顶部环线 Gizmos.DrawLine(topPoint, topNextPoint); // 绘制底部环线 Gizmos.DrawLine(bottomPoint, bottomNextPoint); } } }