버전:2021.3+
이 예시에서는 UI 툴킷의 드래그 이벤트와 UnityEditor.DragAndDrop
클래스를 사용하여 창 간에 드래그 앤 드롭 UI를 활성화하는 방법을 보여줍니다.
이 예시에서는 두 개의 커스텀 에디터 창을 생성합니다.에셋을 프로젝트(Project) 창에서 에디터 창으로 드래그할 수 있습니다.또한 동일한 에셋을 한 창에서 다른 창으로 드래그할 수 있습니다.
이 예시에서 생성한 완성된 파일은 GitHub 저장소에서 확인할 수 있습니다.
이 가이드는 Unity 에디터, UI 툴킷, C# 스크립팅에 익숙한 개발자용입니다.시작하기 전에 먼저 다음을 숙지하십시오.
빌트인 시각적 요소가 있는 UXML 파일에 각 에디터 창의 콘텐츠를 정의합니다.각 에디터 창에는 배경, 헤더, 드롭 영역, 텍스트가 있습니다.USS 파일에 시각적 요소의 스타일을 지정합니다.
임의의 템플릿을 사용하여 Unity 프로젝트를 생성합니다.
drag-and-drop-across-window
라는 이름의 폴더를 만들어 모든 파일을 저장합니다.
다음 콘텐츠가 포함된 DragAndDrop.uxml
이라는 이름의 UI 문서를 생성합니다.
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:VisualElement class="background">
<ui:VisualElement class="header">
<ui:Label text="Drag And Drop Sample" display-tooltip-when-elided="true" class="header__label" />
</ui:VisualElement>
<ui:VisualElement class="drop-area">
<ui:Label text="Drag an asset here..." display-tooltip-when-elided="true" class="drop-area__label" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
다음 콘텐츠가 포함된 DragAndDrop.uss
라는 이름의 스타일시트를 생성합니다.
.background {
flex-grow:1;
background-color: rgba(30, 30, 30, 255);
}
.header {
align-items: center;
margin-left:10px;
margin-right:10px;
margin-top:10px;
margin-bottom:10px;
padding-left:5px;
padding-right:5px;
padding-top:5px;
padding-bottom:5px;
background-color: rgba(112, 128, 144, 255);
border-left-color: rgba(211, 211, 211, 255);
border-right-color: rgba(211, 211, 211, 255);
border-top-color: rgba(211, 211, 211, 255);
border-bottom-color: rgba(211, 211, 211, 255);
border-left-width:2px;
border-right-width:2px;
border-top-width:2px;
border-bottom-width:2px;
}
.header__label {
font-size:18px;
color: rgba(255, 255, 255, 255);
}
.drop-area {
flex-grow:1;
align-items: center;
justify-content: center;
margin-left:10px;
margin-right:10px;
margin-top:10px;
margin-bottom:10px;
padding-left:5px;
padding-right:5px;
padding-top:5px;
padding-bottom:5px;
background-color: rgba(112, 128, 144, 255);
border-left-color: rgba(211, 211, 211, 255);
border-right-color: rgba(211, 211, 211, 255);
border-top-color: rgba(211, 211, 211, 255);
border-bottom-color: rgba(211, 211, 211, 255);
border-left-width:2px;
border-right-width:2px;
border-top-width:2px;
border-bottom-width:2px;
border-top-left-radius:20px;
border-bottom-left-radius:20px;
border-top-right-radius:20px;
border-bottom-right-radius:20px;
}
.drop-area--dropping {
opacity:0.4;
background-color: rgba(0, 100, 0, 255);
}
.drop-area__label {
-unity-font-style: italic;
color: rgba(255, 255, 255, 255);
}
DragAndDrop.xml
을 더블 클릭하여 UI 빌더에서 엽니다.
DragAndDrop.uss
를 기존 USS로 추가합니다.
매니퓰레이터는 입력과 관련된 이벤트 콜백을 등록하고 등록 취소하는 오브젝트입니다.C# 스크립트에서 커스텀 매니퓰레이터를 생성하여 에디터 창에 포인터 이벤트와 드래그 이벤트를 등록합니다.
drag-and-drop-across-window
폴더에 Editor
라는 이름의 폴더를 만듭니다.
Editor
폴더에 다음 콘텐츠가 포함된 DragAndDropManipulator.cs
라는 이름의 C# 파일을 생성합니다.
using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
namespace Samples.Editor.General
{
// The DragAndDropManipulator class is a private class within DragAndDropWindow.
public partial class DragAndDropWindow
{
// DragAndDropManipulator is a manipulator that stores pointer-related callbacks, so it inherits from
// PointerManipulator.
class DragAndDropManipulator :PointerManipulator
{
// The Label in the window that shows the stored asset, if any.
Label dropLabel;
// The stored asset object, if any.
Object droppedObject = null;
// The path of the stored asset, or the empty string if there isn't one.
string assetPath = string.Empty;
public DragAndDropManipulator(VisualElement root)
{
// The target of the manipulator, the object to which to register all callbacks, is the drop area.
target = root.Q<VisualElement>(className:"drop-area");
dropLabel = root.Q<Label>(className:"drop-area__label");
}
protected override void RegisterCallbacksOnTarget()
{
// Register a callback when the user presses the pointer down.
target.RegisterCallback<PointerDownEvent>(OnPointerDown);
// Register callbacks for various stages in the drag process.
target.RegisterCallback<DragEnterEvent>(OnDragEnter);
target.RegisterCallback<DragLeaveEvent>(OnDragLeave);
target.RegisterCallback<DragUpdatedEvent>(OnDragUpdate);
target.RegisterCallback<DragPerformEvent>(OnDragPerform);
}
protected override void UnregisterCallbacksFromTarget()
{
// Unregister all callbacks that you registered in RegisterCallbacksOnTarget().
target.UnregisterCallback<PointerDownEvent>(OnPointerDown);
target.UnregisterCallback<DragEnterEvent>(OnDragEnter);
target.UnregisterCallback<DragLeaveEvent>(OnDragLeave);
target.UnregisterCallback<DragUpdatedEvent>(OnDragUpdate);
target.UnregisterCallback<DragPerformEvent>(OnDragPerform);
}
// This method runs when a user presses a pointer down on the drop area.
void OnPointerDown(PointerDownEvent _)
{
// Only do something if the window currently has a reference to an asset object.
if (droppedObject != null)
{
// Clear existing data in DragAndDrop class.
DragAndDrop.PrepareStartDrag();
// Store reference to object and path to object in DragAndDrop static fields.
DragAndDrop.objectReferences = new[] { droppedObject };
if (assetPath != string.Empty)
{
DragAndDrop.paths = new[] { assetPath };
}
else
{
DragAndDrop.paths = new string[] { };
}
// Start a drag.
DragAndDrop.StartDrag(string.Empty);
}
}
// This method runs if a user brings the pointer over the target while a drag is in progress.
void OnDragEnter(DragEnterEvent _)
{
// Get the name of the object the user is dragging.
var draggedName = string.Empty;
if (DragAndDrop.paths.Length > 0)
{
assetPath = DragAndDrop.paths[0];
var splitPath = assetPath.Split('/');
draggedName = splitPath[splitPath.Length - 1];
}
else if (DragAndDrop.objectReferences.Length > 0)
{
draggedName = DragAndDrop.objectReferences[0].name;
}
// Change the appearance of the drop area if the user drags something over the drop area and holds it
// there.
dropLabel.text = $"Dropping '{draggedName}'...";
target.AddToClassList("drop-area--dropping");
}
// This method runs if a user makes the pointer leave the bounds of the target while a drag is in progress.
void OnDragLeave(DragLeaveEvent _)
{
assetPath = string.Empty;
droppedObject = null;
dropLabel.text = "Drag an asset here...";
target.RemoveFromClassList("drop-area--dropping");
}
// This method runs every frame while a drag is in progress.
void OnDragUpdate(DragUpdatedEvent _)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
}
// This method runs when a user drops a dragged object onto the target.
void OnDragPerform(DragPerformEvent _)
{
// Set droppedObject and draggedName fields to refer to dragged object.
droppedObject = DragAndDrop.objectReferences[0];
string draggedName;
if (assetPath != string.Empty)
{
var splitPath = assetPath.Split('/');
draggedName = splitPath[splitPath.Length - 1];
}
else
{
draggedName = droppedObject.name;
}
// Visually update target to indicate that it now stores an asset.
dropLabel.text = $"Containing '{draggedName}'...\n\n" *
$"(You can also drag from here)";
target.RemoveFromClassList("drop-area--dropping");
}
}
}
}
C# 스크립트에서 두 개의 커스텀 에디터 창을 생성하고 각 에디터 창에 매니퓰레이터를 인스턴스화합니다.
다음 콘텐츠가 포함된 DragAndDropWindow.cs
라는 이름의 C# 파일을 생성합니다.
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace Samples.Editor.General
{
public partial class DragAndDropWindow :EditorWindow
{
// This is the visual tree that contains the UI structure of the window.
[SerializeField]
VisualTreeAsset uxmlAsset;
// This manipulator contains all of the event logic for this window.
DragAndDropManipulator manipulator;
// This is the minimum size of both windows.
readonly static Vector2 windowMinSize = new(300, 180);
// These are the starting positions of the windows.
readonly static Vector2 windowAPosition = new(50, 50);
readonly static Vector2 windowBPosition = new(450, 100);
// These are the titles of the windows.
const string windowATitle = "Drag and Drop A";
const string windowBTitle = "Drag and Drop B";
// This method opens two DragAndDropWindows when a user selects the specified menu item.
[MenuItem("Window/UI Toolkit/Drag And Drop (Editor)")]
public static void OpenDragAndDropWindows()
{
// Create the windows.
var windowA = CreateInstance<DragAndDropWindow>();
var windowB = CreateInstance<DragAndDropWindow>();
// Define the attributes of the windows and display them.
windowA.minSize = windowMinSize;
windowB.minSize = windowMinSize;
windowA.Show();
windowB.Show();
windowA.titleContent = new(windowATitle);
windowB.titleContent = new(windowBTitle);
windowA.position = new(windowAPosition, windowMinSize);
windowB.position = new(windowBPosition, windowMinSize);
}
void OnEnable()
{
if (uxmlAsset != null)
{
uxmlAsset.CloneTree(rootVisualElement);
}
// Instantiate manipulator.
manipulator = new(rootVisualElement);
}
void OnDisable()
{
// The RemoveManipulator() method calls the Manipulator's UnregisterCallbacksFromTarget() method.
manipulator.target.RemoveManipulator(manipulator);
}
}
}
프로젝트 창에서 DragAndDropWindow.cs
를 선택하고 DragAndDrop.xml`을 인스펙터의 Uxml 에셋으로 드래그합니다.
메뉴에서 Window > UI Toolkit > Drag and Drop(Editor)을 선택합니다.두 개의 Drag and Drop 창이 열립니다.에셋을 프로젝트 창에서 이러한 창의 드롭 영역으로 드래그할 수 있습니다.또한 동일한 에셋을 한 창에서 다른 창으로 드래그할 수 있습니다.
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.