Unity编辑器(一)-- 自定义UI拖拽

没有专门处理UI界面岗位的情况下, 开发者需要自己拼合界面,但是Unity默认的UI创建方式有些不太舒服,需要先Create再选中UI最后才能选中自己想要的UI生成出来,而且创建列表内容较多,没办法直接一眼找到,所以做了一个自定义的UI拖拽,先上示例。

 //视频上传维护中。。

 核心思路:

1.创建一个单独编辑器面板

2.可自定义配置UI资源,包括自定义的UI界面

3.可通过拖拽的方式生成对应UI

技术点梳理:

1.EditorWindow,用于制作单独编辑器面板

2.DragAndDrop,用于实现核心拖拽功能

API分析:

相关API可以在Unity官方文档中查看,这里只是我的个人理解。

DragAndDrop.StartDrag

开始拖动操作,在启动拖动之后才有相关的拖拽数据产生,EventType才会触发DragUpdated等与拖拽相关的事件。

DragAndDrop.GetGenericData:

DragAndDrop.SetGenericData

用于对拖拽数据的赋值和获取。

DragAndDrop.PrepareStartDrag:

清空拖拽数据以及拖拽对象,用于数据初始化。

DragAndDrop.AcceptDrag:

接受拖动操作,相当于一个触发器。

DragAndDrop.visualMode

Unity原生的用于修改拖拽时的鼠标样式。

脚本中并没有写有关于生成的逻辑,只有对数据的储存,操作以及DragAndDrop的逻辑,这是因为在Drag的底层调用了Unity原生的生成逻辑,也就是DragAndDropVisualMode.Copy,猜想这部分的逻辑和对预制体拖拽的逻辑是一套的,目前没有查到相关的信息,大佬可留言指教。

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

public class UITool : EditorWindow
{
    class Item
    {
        public GameObject prefab;
        public Texture tex;
    }


    [MenuItem("Tools/UITool")]
    public static void OpenUITool()
    {
        UITool tool = EditorWindow.GetWindow<UITool>(false,"UITool",true);
        tool.autoRepaintOnSceneChange = true;
        tool.Show();
    }

    private Dictionary<string, Item> creatItemDic = new Dictionary<string, Item>();
    private List<Item> creatItemLst = new List<Item>();
    private void OnEnable()
    {
        creatItemDic.Clear();
        creatItemLst.Clear();
        object[] uiPrefabs = Resources.LoadAll("UIPrefab");
        string prefabName = string.Empty;
        for (int i = 0; i < uiPrefabs.Length; i++)
        {
            Item item = new Item();
            item.prefab = uiPrefabs[i] as GameObject;
            prefabName = item.prefab.name;
            Texture tex = Resources.Load<Texture>("UITexture/" + prefabName);
            if (tex == null)
            {
                tex = Resources.Load<Texture>("Unity");
            }
            item.tex = tex;
            creatItemDic.Add(prefabName+i, item);
            creatItemLst.Add(item);
        }
        //可增加自定义路径
;    }


    private Vector2 mPos = Vector2.zero;
    private int cellSize = 65;
    const int cellPaddingX = 10;
    const int cellPaddingY = 15;
    Event curEvent;
    EventType eventType;
    int curIndex = -1;

    int spacingX = 0;
    int spacingY = 0;

    private void OnGUI()
    { 
        RefreshGridPos();
        
        curEvent = Event.current; 
        eventType = curEvent.type;
        curIndex = GetCellUnderMouse(spacingX, spacingY);


        switch (eventType)
        {
            case EventType.MouseDown:
                if (curIndex < creatItemLst.Count)
                {
                    Item item = creatItemLst[curIndex];
                    DraggedObject = item.prefab;
                    Debug.Log(curIndex);
                }
                else
                {
                    DraggedObject = null;
                    Debug.Log("越界");
                }
                break;
            case EventType.MouseDrag:
                if (isDragObjectInOur)
                    DragAndDrop.StartDrag("UITool");
                curEvent.Use();
                break;
            case EventType.DragUpdated:
                UpdateVisual();
                curEvent.Use();
                break;
            default:
                break;
        }
       
    }


    
    void RefreshGridPos()
    {
        GUILayout.BeginVertical();
        mPos = EditorGUILayout.BeginScrollView(mPos);
        Color normal = new Color(1f, 1f, 1f, 0.5f);
       
        Rect texRect;
        Rect labelRect;
        int x = cellPaddingX, y = cellPaddingY;
        int width = Screen.width - cellPaddingX;
        spacingX = cellSize + cellPaddingX;
        spacingY = cellSize + cellPaddingY;

        int offsetCellSize = cellSize - 10;
        var labelStyle = EditorStyles.label;
        labelStyle.alignment = TextAnchor.LowerCenter;
        labelStyle.fontStyle = FontStyle.Bold;
        labelStyle.wordWrap = true;
        foreach (var item in creatItemDic)
        {
            texRect = new Rect(x ,y, offsetCellSize, offsetCellSize);
            Rect inner = texRect;
            inner.xMin -= 8f;
            inner.xMax += 8f;
            GUI.DrawTexture(texRect, item.Value.tex);
            inner.y += 14.5f;
            GUI.Label(inner, item.Value.prefab.name, labelStyle);

            GUI.backgroundColor = Color.black;
            x += spacingX;

            if (x + spacingX > width)
            {
                y += spacingY;
                x = cellPaddingX;
            }
        }
        GUILayout.Space(y + spacingY);
        EditorGUILayout.EndScrollView();

     
        GUILayout.EndHorizontal();
    
    }


   
    int GetCellUnderMouse(int spacingX, int spacingY)
    {
        Vector2 pos = Event.current.mousePosition + mPos;
        int x = cellPaddingX, y = cellPaddingY;
        if (pos.y < y) return -1;

        float width = Screen.width - cellPaddingX + mPos.x;
        float height = Screen.height - cellPaddingY + mPos.y;
        int index = 0;

        for (; ; ++index)
        {
            Rect rect = new Rect(x, y, spacingX, spacingY);
            if (rect.Contains(pos)) break;

            x += spacingX;

            if (x + spacingX > width)
            {
                if (pos.x > x) return -1;
                y += spacingY;
                x = cellPaddingX;
                if (y + spacingY > height) return -1;
            }
        }
        return index;
    }


    bool isDragObjectInOur
    {
        get
        {
            object obj = DragAndDrop.GetGenericData("UITool");
            if (obj == null) return false;
            return (bool)obj;
        }
        set
        {
            DragAndDrop.SetGenericData("UITool", value);
        }
    }

    GameObject draggedObject;
    GameObject DraggedObject
    {
        get 
        {
            return draggedObject; 
        }
        set { draggedObject = value;
            if (draggedObject != null)
            {
                DragAndDrop.PrepareStartDrag();
                DragAndDrop.objectReferences = new Object[] { draggedObject };
                isDragObjectInOur = true;
            }
            else
            {
                DragAndDrop.AcceptDrag();
            }
        }
    }

    void UpdateVisual()
    {
        if (DraggedObject == null) DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
        else if (isDragObjectInOur) DragAndDrop.visualMode = DragAndDropVisualMode.Move;
        else DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
    }
}

Github上有个不错的插件:https://github.com/liuhaopen/UGUI-Editor

 Over!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值