Unity Editor Scene面板下绘制路径点

本文介绍了一个Unity自定义编辑器窗口的例子,该窗口能在场景视图中绘制一个由三点构成的三角形,并使用箭头指示方向。通过简单的代码展示了如何创建自定义编辑器窗口并实现场景GUI操作。

简单粗暴上代码。

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class SceneWindow : EditorWindow
{
    private Vector3[] points = new Vector3[3]
    {
        new Vector3(){x = 0,y =0,z = 0},
        new Vector3() {x = 2,y= 0,z=0},
        new Vector3(){x=2,y=0,z=1}
    };
    [MenuItem("Tools/SceneWindow")]
    static void Open()
    {
        CreateWindow<SceneWindow>();
    }
    public void OnEnable()
    {
        SceneView.duringSceneGui -= OnSceneGUI;
        SceneView.duringSceneGui += OnSceneGUI;
    }

    public void OnDestroy()
    {
        SceneView.duringSceneGui -= OnSceneGUI;
    }

    public void OnSceneGUI(SceneView view)
    {
        Handles.color = Color.blue;
        for (int i = 0; i < 3; i++)
        {
            Handles.Label(points[i],$"点{i}", new GUIStyle() { fontSize = 20 });
        }
        for (int i = 0; i < 2; i++)
        {
            Vector3 from = points[i];
            Vector3 to = points[i + 1];
            Handles.DrawLine(from, to);

            //绘制方向箭头
            Vector3 middle = (from + to) * 0.5f;

            Vector3 v0 = from - to;
            v0 *= 2 / v0.magnitude;
            Vector3 v1 = new Vector3(v0.x * 0.866f - v0.z * 0.5f, v0.y * 0.866f, v0.x * 0.5f + v0.z * 0.866f);
            Vector3 v2 = new Vector3(v0.x * 0.866f + v0.z * 0.5f, v0.y * 0.866f, v0.x * -0.5f + v0.z * 0.866f);
            Handles.DrawAAPolyLine(3, middle + v1, middle, middle + v2);
        }
    }
}

在这里插入图片描述

<think>我们正在讨论的是在UnityEditorWindow中使用Gizmos进行绘制。但是,请注意,Gizmos通常用于场景视图(Scene View)中,而EditorWindow是一个独立的编辑器窗口。在EditorWindow中,我们无法直接使用Gizmos,因为Gizmos的绘制是与场景视图关联的。 然而,我们可以通过其他方式在EditorWindow中实现类似的可视化效果。一种常见的方法是使用Handles类(在UnityEditor命名空间中)或者使用GUI绘图方法(在EditorWindow的OnGUI方法中)。但是,这些方法通常用于在场景视图中绘制,或者是在Inspector的自定义编辑器中。 但是,如果我们确实需要在EditorWindow中绘制图形,我们可以考虑以下两种方法: 1. 在EditorWindow中创建一个自定义的绘制区域(例如,使用一个RenderTexture或者一个自定义的GUI区域),然后使用GL类或者Graphics.DrawTexture等方法进行绘制。 2. 创建一个隐藏的游戏对象,将绘制代码放在该游戏对象的OnDrawGizmos方法中,这样Gizmos就会在场景视图中绘制。然后,我们可以通过EditorWindow来控制这个游戏对象,并同步更新。但是,这种方法并不是在EditorWindow内部绘制,而是在场景视图中。 根据问题,用户希望的是在EditorWindow中使用Gizmos,这通常不可行,因为Gizmos是绘制在场景视图中的。因此,我们需要在EditorWindow中创建一个可以绘图的区域,然后使用其他绘图API。 这里,我们介绍一种在EditorWindow中绘制的方法:使用GL类在EditorWindow中绘制。我们可以创建一个自定义的EditorWindow,并在其中创建一个区域,然后使用GL进行即时模式绘图。 以下是一个简单的示例,展示如何在EditorWindow中绘制一个矩形区域,并在其中使用GL绘制图形: 步骤: 1. 创建一个继承自EditorWindow的类。 2. 在OnGUI方法中,创建一个区域(例如,使用GUILayout.BeginArea或GUI.BeginGroup)作为我们的绘图区域。 3. 在这个区域内,我们可以使用GL类进行绘图。但是,GL绘图需要在一个特定的上下文(如:在RenderTexture上)或者在一个GUI控件中(如:通过EditorGUI.DrawPreviewTexture)。我们可以使用一个自定义的RenderTexture,然后将其绘制到GUI中。 但是,更简单的方式是使用Handles和GUI绘图,但注意Handles只能在场景视图中使用。因此,我们选择使用GL类,并配合一个可绘制的纹理区域。 然而,在EditorWindow中直接使用GL绘图比较复杂。另一种方法是使用Graphics.DrawTexture来绘制一个纹理,然后在这个纹理上使用GL绘图,但这需要额外的渲染纹理和材质。 实际上,Unity提供了一个EditorGUI.DrawPreviewTexture方法,它可以让我们在GUI中绘制一个纹理,并且我们可以在这个纹理上使用GL进行绘制。但是,这需要我们将GL绘制的内容渲染到一张RenderTexture上,然后再将这个RenderTexture绘制到GUI中。 由于这个过程较为复杂,我们可以考虑使用Unity的Handles类在场景视图中绘制,然后在EditorWindow中通过按钮等控制绘制的内容。但这样就不是在EditorWindow内部了。 如果用户坚持要在EditorWindow内部绘制,我们可以使用GUI绘图API(如GUI.DrawTexture)来绘制一些简单的图形,或者使用GL类在GUI中绘制,但这需要一些技巧。 这里有一个折中的方法:我们可以创建一个自定义的EditorWindow,并在其中创建一个区域,然后在这个区域中绘制一个矩形,并在这个矩形内使用GL进行绘图。但是,GL绘图需要在一个BeginGroup和EndGroup的上下文中,并且需要设置好矩阵和材质。 以下是一个示例代码,展示如何在EditorWindow中绘制一个三角形: ```csharp using UnityEditor; using UnityEngine; public class MyGizmosWindow : EditorWindow { [MenuItem("Window/My Gizmos Window")] static void Init() { MyGizmosWindow window = (MyGizmosWindow)EditorWindow.GetWindow(typeof(MyGizmosWindow)); window.Show(); } void OnGUI() { // 创建一个矩形区域,我们将在其中绘制 Rect rect = GUILayoutUtility.GetRect(200, 200); if (Event.current.type == EventType.Repaint) { // 设置绘制区域 GUI.BeginClip(rect); GL.PushMatrix(); // 设置GL的绘制矩阵,以匹配GUI区域 GL.LoadPixelMatrix(); // 设置绘制材质(使用UI默认材质) Material mat = new Material(Shader.Find("UI/Default")); mat.SetPass(0); // 开始绘制三角形 GL.Begin(GL.TRIANGLES); GL.Color(Color.red); GL.Vertex3(0, 0, 0); GL.Vertex3(rect.width, 0, 0); GL.Vertex3(rect.width / 2, rect.height, 0); GL.End(); GL.PopMatrix(); GUI.EndClip(); } } } ``` 注意:上述代码在OnGUI的Repaint事件中绘制,使用GL立即模式绘制了一个三角形。我们使用GUI.BeginClip将绘制区域限制在rect内,然后使用GL.LoadPixelMatrix将坐标转换为像素坐标(左下角为原)。 但是,这种方法在EditorWindow中绘制复杂图形时可能会遇到性能问题,并且需要处理事件(如鼠标事件)来实现交互。 另外,我们也可以考虑使用Unity的UIElements系统,它提供了更现代的方式来创建编辑器UI,并且可以使用IMGUI的绘图API或者通过自定义的VisualElement来绘制图形。 但是,由于问题要求使用Gizmos,而Gizmos在EditorWindow中不可用,所以上述方法提供了一种替代方案。 结论:在EditorWindow中无法直接使用Gizmos,但可以使用GL类或GUI绘图API来实现类似的可视化效果。 相关问题: 1. 如何在Unity EditorWindow中处理鼠标事件以实现交互式绘图? 2. 如何使用Unity的UIElements在EditorWindow中绘制自定义图形? 3. 在Unity编辑器扩展中,Gizmos和Handles有什么区别? 4. 如何在场景视图中通过EditorWindow控制绘制Gizmos?</think>在Unity EditorWindow中使用Gizmos绘制调试图形需要特殊处理,因为Gizmos默认只在场景视图(Scene View)中渲染。以下是实现方法: ### 解决方案 1. **创建自定义EditorWindow** ```csharp using UnityEditor; using UnityEngine; public class GizmoWindow : EditorWindow { [MenuItem("Tools/Gizmo Window")] static void Init() => GetWindow<GizmoWindow>("Gizmo Visualizer"); void OnGUI() { // 请求场景视图重绘 if (Event.current.type == EventType.Repaint) SceneView.RepaintAll(); } } ``` 2. **添加Gizmos绘制逻辑** ```csharp #if UNITY_EDITOR using UnityEditor; #endif public class GizmoDrawer : MonoBehaviour { #if UNITY_EDITOR void OnDrawGizmos() { // 仅在目标窗口打开时绘制 if (EditorWindow.HasOpenInstances<GizmoWindow>()) { Gizmos.color = Color.red; Gizmos.DrawWireCube(Vector3.zero, Vector3.one * 2); Gizmos.color = Color.green; Gizmos.DrawSphere(Vector3.up, 0.5f); } } #endif } ``` ### 关键说明 1. **场景视图联动** 通过`SceneView.RepaintAll()`强制场景视图刷新,使Gizmos实时更新[^2]。此方法在`OnGUI`的`Repaint`事件中调用最有效。 2. **条件渲染控制** 使用`EditorWindow.HasOpenInstances<GizmoWindow>()`确保Gizmos仅在自定义窗口打开时显示[^4]。 3. **Gizmos绘制位置** Gizmos的世界坐标系基于**场景视图原**,使用`Vector3.zero`表示场景中心。坐标系遵循左手定则: $$ \begin{cases} x+ : \text{右} \\ y+ : \text{上} \\ z+ : \text{前} \end{cases} $$ ### 优化建议 - 添加窗口控制参数: ```csharp // 在GizmoWindow类中添加 public static bool ShowGizmos = true; void OnGUI() { ShowGizmos = EditorGUILayout.Toggle("Enable Gizmos", ShowGizmos); // ...其他代码 } ``` - 在GizmoDrawer中替换判断条件: ```csharp if (GizmoWindow.ShowGizmos && EditorWindow.HasOpenInstances<GizmoWindow>()) ``` ### 备选方案 对于**纯EditorWindow内绘制**(无场景视图依赖): ```csharp void OnGUI() { Handles.BeginGUI(); Handles.color = Color.blue; Handles.DrawWireCube(position.size / 2, position.size * 0.8f); Handles.EndGUI(); } ``` > 使用`Handles`类直接在窗口绘制,但功能受限且无深度缓冲[^1][^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JustEasyCode

谢谢您

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值