(client) feat:添加UI多线段绘制器,贝塞尔曲线绘制器及其编辑器, fix:单目标子弹在一帧内击中多个目标未被限制击中数量

This commit is contained in:
m0_75251201
2025-09-09 20:10:21 +08:00
parent 6cb4483d20
commit d1c0387df0
17 changed files with 1142 additions and 117 deletions

View File

@ -0,0 +1,144 @@
using UI;
using UnityEditor;
using UnityEngine;
namespace Editor
{
// 告诉 Unity 这个编辑器是为 UIBezierCurveGenerator 组件服务的
[CustomEditor(typeof(UIBezierCurveGenerator))]
public class UIBezierCurveGeneratorEditor : UnityEditor.Editor
{
// 这个方法用于定义组件在 Inspector 窗口中的显示
public override void OnInspectorGUI()
{
// 调用基类的 OnInspectorGUI 方法,绘制所有 public 或 [SerializeField] 字段
// 这意味着我们会看到 P0, P1, P2, P3 和 segmentCount 的默认 Inspector 控件
base.OnInspectorGUI();
// 获取目标组件的引用
UIBezierCurveGenerator generator = (UIBezierCurveGenerator)target;
// 可以在这里添加自定义的 Inspector 按钮或信息
if (GUILayout.Button("Generate Curve Now"))
{
generator.GenerateCurvePoints();
}
}
// 这个方法用于在 Scene 视图中绘制 Gizmos 或处理交互
protected virtual void OnSceneGUI()
{
// 获取当前被选中的 UIBezierCurveGenerator 实例
UIBezierCurveGenerator generator = (UIBezierCurveGenerator)target;
RectTransform rectTransform = generator.GetComponent<RectTransform>();
// 如果没有 RectTransform 或 UILineRenderer则无法操作直接返回
if (rectTransform == null || generator.lineRenderer == null) // lineRenderer 现已为 public
{
return;
}
// 确保在 Scene 视图中显示时重新生成曲线
// 这有助于在编辑器中实时预览,即使 Inspector 没有变动。
// 但要注意,频繁调用 GenerateCurvePoints() 可能对性能有轻微影响,
// 但对于贝塞尔曲线这种操作,通常是可以接受的。
generator.GenerateCurvePoints();
// 设置 Unity Editor Handles 的颜色,方便区分不同的点
Handles.color = Color.white;
// 修正:使用 HandleUtility.GetHandleSize 方法,并根据 P0 的世界位置计算句柄大小
float handleSphereSize =
HandleUtility.GetHandleSize(rectTransform.TransformPoint(generator.P0)) * 0.05f; // 调整一个合适的大小比例
// =========================================================
// P0 (起点) 的操作
// =========================================================
Handles.color = Color.green; // 绿色表示起点
Vector3 worldP0 = rectTransform.TransformPoint(generator.P0); // 将 P0 从局部坐标转换为世界坐标
EditorGUI.BeginChangeCheck(); // 开始检查是否有改变发生
// 绘制一个可拖动的 PositionHandle返回用户拖动后的新世界坐标
worldP0 = Handles.PositionHandle(worldP0, Quaternion.identity);
if (EditorGUI.EndChangeCheck()) // 如果 PositionHandle 被拖动,检测到改变
{
Undo.RecordObject(generator, "Move Bezier Point P0"); // 记录操作,支持撤销
generator.P0 = rectTransform.InverseTransformPoint(worldP0); // 将新的世界坐标转换回局部坐标
generator.GenerateCurvePoints(); // 立即更新曲线 (调用组件的方法)
EditorUtility.SetDirty(generator); // 标记组件已修改,确保保存到场景
}
Handles.DrawSolidDisc(worldP0, Vector3.forward, handleSphereSize * 0.8f); // 绘制一个小圆盘作为点标记
// =========================================================
// P1 (第一个控制点) 的操作
// =========================================================
Handles.color = Color.blue; // 蓝色表示第一个控制点
Vector3 worldP1 = rectTransform.TransformPoint(generator.P1);
EditorGUI.BeginChangeCheck();
worldP1 = Handles.PositionHandle(worldP1, Quaternion.identity);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(generator, "Move Bezier Point P1");
generator.P1 = rectTransform.InverseTransformPoint(worldP1);
generator.GenerateCurvePoints();
EditorUtility.SetDirty(generator);
}
Handles.DrawSolidDisc(worldP1, Vector3.forward, handleSphereSize * 0.6f);
// =========================================================
// P2 (第二个控制点) 的操作
// =========================================================
Handles.color = Color.magenta; // 洋红色表示第二个控制点
Vector3 worldP2 = rectTransform.TransformPoint(generator.P2);
EditorGUI.BeginChangeCheck();
worldP2 = Handles.PositionHandle(worldP2, Quaternion.identity);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(generator, "Move Bezier Point P2");
generator.P2 = rectTransform.InverseTransformPoint(worldP2);
generator.GenerateCurvePoints();
EditorUtility.SetDirty(generator);
}
Handles.DrawSolidDisc(worldP2, Vector3.forward, handleSphereSize * 0.6f);
// =========================================================
// P3 (终点) 的操作
// =========================================================
Handles.color = Color.red; // 红色表示终点
Vector3 worldP3 = rectTransform.TransformPoint(generator.P3);
EditorGUI.BeginChangeCheck();
worldP3 = Handles.PositionHandle(worldP3, Quaternion.identity);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(generator, "Move Bezier Point P3");
generator.P3 = rectTransform.InverseTransformPoint(worldP3);
generator.GenerateCurvePoints();
EditorUtility.SetDirty(generator);
}
Handles.DrawSolidDisc(worldP3, Vector3.forward, handleSphereSize * 0.8f);
// =========================================================
// 绘制辅助线 (控制杆),连接起点到第一个控制点,终点到第二个控制点
// =========================================================
Handles.color = Color.gray; // 灰色辅助线
Handles.DrawLine(worldP0, worldP1); // P0 -> P1
Handles.DrawLine(worldP2, worldP3); // P2 -> P3
// 刷新 Scene 视图,确保所有 Gizmos 和曲线更新立即显示
SceneView.RepaintAll();
}
}
}