Unity Editor Window 拖拽调整区域大小

该代码示例展示了如何在Unity3D中创建一个自定义的EditorWindow,包含可拖动的分割线,允许用户调整左右两个滚动视图的大小。用户可以按需调整左侧和右侧区域的显示空间。

效果示意

Rect Drag

代码示例

using UnityEngine;
using UnityEditor;

public class ExampleEditorWindow : EditorWindow
{
    private Vector2 lScrollPosition, rScrollPosition;
    //分割线宽度
    private const float splitterWidth = 2f;
    //分割线位置
    private float splitterPos;
    private Rect splitterRect;
    //是否正在拖拽分割线
    private bool isDragging;

    [MenuItem("SKFramework/Example Editor Window")]
    public static void Open()
    {
        GetWindow<ExampleEditorWindow>().Show();
    }

    private void OnEnable()
    {
        splitterPos = position.width * .3f;
    }

    internal void OnGUI()
    {
        GUILayout.BeginHorizontal();
        {
            lScrollPosition = GUILayout.BeginScrollView(lScrollPosition, GUILayout.Width(splitterPos), GUILayout.MaxWidth(splitterPos), GUILayout.MinWidth(splitterPos));
            OnLeftGUI();
            GUILayout.EndScrollView();

            //分割线
            GUILayout.Box(string.Empty, GUILayout.Width(splitterWidth), GUILayout.MaxWidth(splitterWidth), GUILayout.MinWidth(splitterWidth), GUILayout.ExpandHeight(true));
            splitterRect = GUILayoutUtility.GetLastRect();

            rScrollPosition = GUILayout.BeginScrollView(rScrollPosition, GUILayout.ExpandWidth(true));
            OnRightGUI();
            GUILayout.EndScrollView();
        }
        GUILayout.EndHorizontal();

        if (Event.current != null)
        {
            //光标
            EditorGUIUtility.AddCursorRect(splitterRect, MouseCursor.ResizeHorizontal);
            switch (Event.current.rawType)
            {
                //开始拖拽分割线
                case EventType.MouseDown:
                    isDragging = splitterRect.Contains(Event.current.mousePosition);
                    break;
                case EventType.MouseDrag:
                    if (isDragging)
                    {
                        splitterPos += Event.current.delta.x;
                        //限制其最大最小值
                        splitterPos = Mathf.Clamp(splitterPos, position.width * .2f, position.width * .8f);
                        Repaint();
                    }
                    break;
                //结束拖拽分割线
                case EventType.MouseUp:
                    if (isDragging)
                        isDragging = false;
                    break;
            }
        }
    }
    private void OnLeftGUI()
    {
        GUILayout.Box("左侧区域", GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
    }

    private void OnRightGUI()
    {
        GUILayout.Box("右侧区域", GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
    }
}
<think>我们参考了多个引用中关于Unity编辑器拖拽区域的实现方法,特别是引用[2]和引用[3]提供了关键代码片段。实现可拖拽区域主要涉及以下步骤: 1. 使用GUILayoutUtility.GetRectEditorGUILayout.GetControlRect获取一个矩形区域作为拖拽区域。 2. 使用GUI.Box或类似方法绘制该区域,以便用户可见。 3. 处理事件(EventType.DragUpdated, EventType.DragPerform等),检查鼠标位置是否在拖拽区域内。 4. 设置DragAndDrop.visualMode来改变鼠标的视觉效果,表示可以拖放。 5. 在DragPerform事件中,调用DragAndDrop.AcceptDrag()来接受拖拽,然后处理拖拽的对象(DragAndDrop.objectReferences)或路径(DragAndDrop.paths)。 下面是一个简单的实现示例,创建一个可拖拽区域,能够接受拖拽的对象(如纹理、预制体等)并在控制台输出信息。 注意:以下代码应放在自定义编辑器窗口(EditorWindow)或自定义Inspector(Editor)的OnGUI方法中。</think>在Unity编辑器中实现可拖拽区域功能,主要通过处理`DragAndDrop`API和GUI事件来实现。以下是核心实现步骤及代码示例: ### 基本实现原理 1. **创建矩形区域**:使用`GUILayoutUtility.GetRect()`定义可拖拽区域范围 2. **事件检测**:通过`Event.current.type`捕获拖拽事件 3. **视觉反馈**:设置`DragAndDrop.visualMode`改变鼠标图标 4. **数据处理**:在`DragPerform`事件中获取拖拽对象 ### 完整代码实现 ```csharp using UnityEditor; using UnityEngine; public class DragDropExample : EditorWindow { [MenuItem("Window/Drag Drop Example")] static void Init() => GetWindow<DragDropExample>("拖拽区域示例"); void OnGUI() { // 1. 创建拖拽区域矩形 Rect dragArea = GUILayoutUtility.GetRect(0f, 100f, GUILayout.ExpandWidth(true)); // 2. 绘制区域背景 GUI.Box(dragArea, "拖拽文件到此处", new GUIStyle(GUI.skin.box) { normal = { background = MakeTex(2, 2, new Color(0.2f, 0.2f, 0.2f, 0.4f)) }, alignment = TextAnchor.MiddleCenter }); // 3. 事件处理 Event currentEvent = Event.current; switch (currentEvent.type) { case EventType.DragUpdated: case EventType.DragPerform: if (dragArea.Contains(currentEvent.mousePosition)) { // 显示复制图标 DragAndDrop.visualMode = DragAndDropVisualMode.Copy; if (currentEvent.type == EventType.DragPerform) { DragAndDrop.AcceptDrag(); // 处理拖拽对象 foreach (Object obj in DragAndDrop.objectReferences) { Debug.Log($"已接收拖拽对象: {obj.name}\n" + $"类型: {obj.GetType()}\n" + $"路径: {AssetDatabase.GetAssetPath(obj)}"); } } currentEvent.Use(); } break; } } // 创建背景纹理的辅助方法 private Texture2D MakeTex(int width, int height, Color col) { Color[] pix = new Color[width * height]; for (int i = 0; i < pix.Length; i++) pix[i] = col; Texture2D result = new Texture2D(width, height); result.SetPixels(pix); result.Apply(); return result; } } ``` ### 关键功能说明 1. **区域定义**: - `GetRect(0f, 100f)`创建高度100px的区域 - `ExpandWidth(true)`使区域宽度自适应 2. **事件处理流程**: ```mermaid graph TD A[鼠标进入区域] --> B{DragUpdated事件} B --> C[设置visualMode=Copy] C --> D{松开鼠标} D --> E[DragPerform事件] E --> F[AcceptDrag接收数据] F --> G[处理objectReferences] ``` 3. **获取的数据类型**: - `DragAndDrop.objectReferences`:资源对象实例 - `DragAndDrop.paths`:资源路径数组 - `DragAndDrop.assetPaths`:Assets目录下的完整路径 ### 实际应用场景 1. **资源管理器**:拖拽导入纹理/模型等资源 2. **数据配置**:拖拽Excel/JSON文件到配置工具 3. **场景编辑器**:拖拽预制体到指定区域生成对象 4. **批量处理工具**:同时拖入多个资源进行自动化处理 ### 进阶优化方案 1. **多类型过滤**: ```csharp // 只接受Texture2D类型 if (obj is Texture2D) { // 处理纹理 } ``` 2. **区域高亮反馈**: ```csharp if (dragArea.Contains(Event.current.mousePosition)) { EditorGUI.DrawRect(dragArea, new Color(0,1,0,0.2f)); } ``` 3. **路径处理优化**: ```csharp string relativePath = DragAndDrop.paths[0].Replace(Application.dataPath, "Assets"); ``` > 注意:在`EditorWindow`中直接使用此代码,在`CustomEditor`中需放在`OnInspectorGUI`方法内[^2][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CoderZ1010

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值