【Unity】自制PolygonCollider2D

防止和UnityEngine的PolygonCollider2D重名,所有类包裹在了我自己定义的名称空间JimDevPack中,名称空间的声明部分在文章代码中略去了。

定义PolygonCollider2D和基类

基类

public class Collider2D : MonoBehaviour {}

PolygonCollider2D

public class PolygonCollider2D : Collider2D
{
    public List<Vector2> points;
    
    // 绘制多边形的边
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.green;
        if (points.Count > 1)
        {
            for (int i = 0; i < points.Count - 1; i++)
            {
                Gizmos.DrawLine(points[i], points[i + 1]);
            }
            Gizmos.DrawLine(points[points.Count - 1], points[0]);
        }
    }
}

Editor扩展

[CustomEditor(typeof(PolygonCollider2D))]
public class PolygonCollider2DEditor : Editor
{
    private PolygonCollider2D polygonCollider;

    private void OnEnable()
    {
        polygonCollider = (PolygonCollider2D)target;
        if (polygonCollider.points == null)
        {
            polygonCollider.points = new List<Vector2>();
        }
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if (GUILayout.Button("Add Point"))
        {
            polygonCollider.points.Add(new Vector2());
        }
    }

    private void OnSceneGUI()
    {
        Event guiEvent = Event.current;

        // 如果按住ctrl并且点击了左键,会删除点击位置最近的点
        if (guiEvent.type == EventType.MouseDown && guiEvent.button == 0 && guiEvent.control)
        {
            float closestDistance = float.MaxValue;
            int closestIndex = -1;

            // 寻找最近的点
            for (int i = 0; i < polygonCollider.points.Count; i++)
            {
                float distance = Vector2.Distance(polygonCollider.points[i], HandleUtility.GUIPointToWorldRay(guiEvent.mousePosition).origin);
                if (distance < closestDistance)
                {
                    closestDistance = distance;
                    closestIndex = i;
                }
            }

            if (closestIndex != -1)
            {
                Undo.RecordObject(polygonCollider, "Remove Point");
                polygonCollider.points.RemoveAt(closestIndex);
                guiEvent.Use();
            }
        }

        for (int i = 0; i < polygonCollider.points.Count; i++)
        {
            Handles.color = new Color(0, 0, 1, 1f);
            EditorGUI.BeginChangeCheck();
            // 绘制一个可自由移动的Handle
            Vector2 newTargetPosition = Handles.FreeMoveHandle(polygonCollider.points[i], Quaternion.identity, 0.03f, new Vector2(0.5f, 0.5f), Handles.DotHandleCap);
            if (EditorGUI.EndChangeCheck())
            {
                // 记录信息,为了响应撤销
                Undo.RecordObject(polygonCollider, "Move Point");
                // 赋值新位置
                polygonCollider.points[i] = newTargetPosition;
            }
        }
    }
}

效果

posted @ 2024-07-14 21:53  JimmyZou  阅读(9)  评论(0编辑  收藏  举报