【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;
}
}
}
}