108 lines
3.8 KiB
C#
108 lines
3.8 KiB
C#
|
|
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<CapsuleCollider>();
|
||
|
|
}
|
||
|
|
|
||
|
|
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<CapsuleCollider>();
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|