下面将利用UnityEditor下的DragAndDrop类拓展Hierarchy窗口下的两种功能。
主要使用其静态方法 AddDropHandler(HierarchyDropHandler handler)
Unity版本:2021.3.23f1c1
一、实现将Assets中的脚本文件拖拽到Hierarchy窗口下,则直接创建一个空物体并加上此脚本关联的组件。
效果:
实现代码:(放Editor文件夹下)
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class DropMonoScriptToHierarchy
{
static DropMonoScriptToHierarchy()
{
DragAndDrop.AddDropHandler(HierarchyDropHandler);
}
private static DragAndDropVisualMode HierarchyDropHandler(int dropTargetInstanceID, HierarchyDropFlags dropMode, Transform parentForDraggedObjects, bool perform)
{
Object obj = EditorUtility.InstanceIDToObject(dropTargetInstanceID);//拖拽放置目标对象
if (!perform)//在拖拽中时
{
//仅支持拖拽1个脚本文件
if (DragAndDrop.objectReferences.Length == 1 && DragAndDrop.objectReferences[0] is MonoScript script)
{
if (obj == null)
return DragAndDropVisualMode.Generic;//放置目标为空时,改变VisualMode
}
}
else//在拖拽放下时
{
if (DragAndDrop.objectReferences.Length == 1 && DragAndDrop.objectReferences[0] is MonoScript script && obj == null)
{
if (typeof(Component).IsAssignableFrom(script.GetClass()))//判定脚本文件的类型是否为组件
Selection.activeObject = new GameObject(script.GetClass().Name, script.GetClass());//创建新物体,并加组件
else
Debug.Log($"非组件脚本文件:{script.name}");
}
}
return DragAndDropVisualMode.None;
}
}
二、将Assets中的Sprite文件拖拽到Hierarchy窗口下的RectTransform对象下,则直接创建一个子RectTransform对象,加上Image组件(sprite设定为拖拽的对象)。
由于Unity将Sprite拖拽到Hierarchy只能创建SpriteRenderer对象,于是做此拓展以实现在UGUI下快速创建Iamge并关联对应的Sprite,同时执行一次SetNativeSize()以调整RectTransform的size与sprite的宽高一致。
实现代码:(放Editor文件夹下)
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[InitializeOnLoad]
public class DropSpriteToHierarchy
{
static DropSpriteToHierarchy()
{
DragAndDrop.AddDropHandler(HierarchyDropHandler);
}
private static DragAndDropVisualMode HierarchyDropHandler(int dropTargetInstanceID, HierarchyDropFlags dropMode, Transform parentForDraggedObjects, bool perform)
{
if (perform)//在拖拽放下时
{
GameObject obj = EditorUtility.InstanceIDToObject(dropTargetInstanceID) as GameObject;//拖拽放置目标对象
if (obj && obj.transform is RectTransform)
{
//拖拽的对象,均应为 Sprite 或着 TextureType为Sprite的Texture2D
bool allIsSpr = DragAndDrop.objectReferences.All(v => CheckIsSprite(v));
if (allIsSpr)
{
List<Object> selObjs = new List<Object>(DragAndDrop.objectReferences.Length);
UnityAction<Sprite> creatFun = (Sprite dragObj) =>
{
var newObj = new GameObject(dragObj.name, typeof(RectTransform), typeof(Image));
newObj.transform.parent = obj.transform;
newObj.transform.localPosition = Vector3.zero;
newObj.GetComponent<Image>().sprite = dragObj;
newObj.GetComponent<Image>().SetNativeSize();
selObjs.Add(newObj);
};
foreach (var dragObj in DragAndDrop.objectReferences)
{
if (dragObj is Sprite)
{
creatFun(dragObj as Sprite);
continue;
}
// 获取选中 Texture2D 对应的路径
string assetPath = AssetDatabase.GetAssetPath(dragObj);
// 加载所有嵌套在 Texture2D 资源中的 Sprite
Object[] sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath(assetPath);
// 检查是否存在 Sprite
foreach (Object t2d in sprites)
{
if (t2d is Sprite)
{
creatFun(t2d as Sprite);
}
}
}
Selection.objects = selObjs.ToArray();
return DragAndDropVisualMode.Generic;
}
}
}
return DragAndDropVisualMode.None;
}
public static bool CheckIsSprite(Object tarObj)
{
if (tarObj is Sprite || tarObj is Texture2D)
{
return true;
}
//else if (tarObj is Texture2D)
//{
// // 获取该Texture的Importer
// string path = AssetDatabase.GetAssetPath(tarObj);
// TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
// // 检查TextureType是否为Sprite
// return importer.textureType == TextureImporterType.Sprite;
//}
return false;
}
}