본문 바로가기
Engine/Unity

Unity Drag & Drop

by 뇌 속의 통 2025. 2. 19.

유니티에서는 기본적으로 Drag & Drop 기능을 지원해줍니다.

Interface로 모두 구현되어 있기 때문에 사용자는 해당 Interface를 이용하여 원하는 로직만 추가하면 됩니다.

 

1. Drag할 Object 설정하기.

Drag 할 Object에는 IBeginDragHanlder(드래그 시작), IDragHandler(드래그중), IEndDragHandler(드래그 종료)를 각각 상속 받는 Script를 하나 추가하여야 합니다.

 

IBeginDragHandler

    public void OnBeginDrag(PointerEventData eventData) 
    {
        transform.SetAsLastSibling();
        GetComponent<Image>().raycastTarget = false;
        eventData.pointerDrag = gameObject;
    }

 

해당 함수에서는 드래그가 시작되면 해당 UI를 Inspector의 가장 마지막 위치로 이동하여 다른 UI에 가려지지 않도록 설정하고, raycastTarget을 반드시 false로 설정하여 Drop시 드래그 중인 UI가 아니라 그 UI 뒤에 위치한 객체가 Drop 되었음을 인지할 수 있도록 설정해야 합니다.

 

만약, raycastTarget을 false로 하지 않으면 Drop 시 Drag 중인 UI가 Raycast를 막아버려서 뒤에 위치한 객체가 Drop됨을 인지 할 수 없습니다.

 

그러면 인자로 받는 PointerEventData는 무엇일까요?

PointerEventData는 UI 이벤트 시스템에서 마우스 Click, 터치, Drag 등의 다양한 입력 이벤트 정보를 저장하는 구조체입니다. 마우스 클릭이나 터치 등이 발생하면 해당 정보를 저장하는 역할을 수행합니다.

 

PointerEventData eventData;

eventData.position // 클릭, 터치한 위치값
eventData.button // 클릭한 마우스 버튼의 종류
eventData.delit // 이전 프레임 대비 포인터의 이동거리
eventData.pointerEnter // 들어간 UI 요소(GameObject)
eventData.pointerDrag // Drag 중인 UI 요소(GameObject)
eventData.clickCount // 클릭한 횟수 (1: 단일, 2: 더블)
eventData.dragging // Drag 중인지 여부

 

이렇게 다양한 정보를 가지고 있습니다.

 

문제 1. 내가 Drag 중인 UI의 Image를 가져와 비활성화 시키세요.

정답 확인

더보기
더보기

eventData.pointerDrag.GetComponent<Image>().enabled = false;

 

IDragHandler

    public void OnDrag(PointerEventData eventData)
    {
        rectTransform.position = eventData.position;
    }

 

Drag를 하는 동안은 해당 Object의 Position을 항상 터치, 마우스가 있는 위치와 동기화를 시켜야하므로 eventData의 position(현재 마우스, 터치의 위치)를 가져와 해당 Object의 Position으로 설정해줍니다.

 

2. Drag를 받을 Droppable Object 설정하기

이제 Drag하는 객체는 설정하였으니 해당 객체를 Drop할 객체를 설정해야합니다.(인벤토리, 특정 UI 등)

Drop을 받을 객체도 미리 구현된 Interface를 이용하여 사용하면 편하게 구현가능합니다.

 

Drop은 각각 IPointerEnterHandler(내 위치로 들어왔는지), IDropHandler(Drop을 했는지), IPointerExitHandler(내 위치에서 나갔는지) Interface를 상속받습니다.

 

IPointerEnterHandler

    public void OnPointerEnter(PointerEventData eventData) 
    {
        if (eventData.pointerDrag != null)
            targetImage.color = Color.gray;
    }

 

만약 마우스 또는 터치위치가 안으로 들어오면 OnPointerEnter 이벤트가 호출됩니다.

 

이때 Drag 중인 GameObject가 있는지 확인하고 있다면 targetImage의 색상을 변경하여 시각적으로 해당 위치에 놓을것임을 사용자에게 알려줍니다.

 

IPointerExitHandler

    public void OnPointerExit(PointerEventData eventData) 
    {
        if(eventData.pointerDrag != null)
            targetImage.color = previousColor;
    }

만약 밖으로 나가게 되면 기존 색상으로 다시 되돌려서 드랍될 위치가 아님을 사용자에게 알려주도록 합니다.

 

IDropHandler

    public void OnDrop(PointerEventData eventData) 
    {
        if (eventData.pointerDrag != null)
        {
            DraggableUI draggableUI = eventData.pointerDrag.GetComponent<DraggableUI>();

            if (draggableUI != null)
            {
                targetImage.color = previousColor;
                draggableUI.GetComponent<Image>().raycastTarget = true;
            }
        }
    }

Drop을 하게 되면 해당 객체가 드래그 가능한 객체인지 확인하여 가능한 객체라면 raycastTarget을 다시 true로 변환합니다. 그래야 다시 Drag가 가능해지기 때문입니다.

 

그리고 Color값도 기존 값으로 변경하여 선택되지 않았음을 사용자에게 알려주어야 합니다.

 

인벤토리와 같은 기능을 구현한다면 해당 객체를 본인의 Layout Group에 추가하는 방식으로 하여 보다 자연스럽게 만들 수 있습니다.

 

이와 같이 각 함수를 추가하면 아래 영상과 같은 로직을 만들 수 있습니다.

 

 

 

'Engine > Unity' 카테고리의 다른 글

Unity에서 JSON 사용하기  (1) 2025.07.07
Unity Coroutine  (0) 2025.02.20
Unity MathF  (0) 2025.02.17
Unity Transform  (2) 2025.02.07
Unity Render Pipeline(URP와 Built-in RP 차이)  (1) 2024.10.24