没有专门处理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!