1 분 소요

Intro

  • 이번 포스팅에서는 인벤토리내의 아이템 드래그 앤 드롭 기능을 구현해보려합니다.

  • 아이템의 드래그 앤 드롭 기능을 구현하는 방법은 다양합니다.

  1. 각 아이템 아이콘마다 스크립트 부여
    • 각 슬롯마다 자식 오브젝트로 아이템의 아이콘이 있습니다.
    • 슬롯의 갯수만큼 아이콘의 갯수가 있을겁니다.
    • 그렇다면 아이콘을 위한 스크립트를 작성하고 각 슬롯의 아이템에 컴포넌트로 넣어줍니다.
    • 드래그 앤 드롭은 포인터 인터페이스로 구현합니다.
  2. 각 슬롯에 스크립트 부여
    • 슬롯을 관리하는 ItemSlotUI에서 드래그 앤 드롭을 구현하는 방법이 있습니다.
  3. 인벤토리 UI 에서 구현
    • 포인터 인터페이스를 사용하지 않고 GraphicRaycaster를 이용하여 InventoryUI 스크립트에서 직접 구현합니다.
  • 각 방법마다 장단점이 있습니다. 여기서는 세번째 방법으로 구현해봅니다.

InventoryUI 클래스


    private GraphicRaycaster gr;
    private PointerEventData ped;
    private List<RaycastResult> rrList;

    private ItemSlotUI beginDragSlot;           // .. 현재 드래그를 시작한 슬롯
    private Transform beginDragIconTransform;   // .. 해당 슬롯의 아이콘

    private Vector3 beginDragIconPoint;         // .. 드래그 시작 시 슬롯 위치
    private Vector3 beginDragCursorPoint;       // .. 드래그 시작 시 커서 위치
    private int beginDragSlotSiblingIndex;

    void Update()
    {
        ped.position = Input.mousePosition;

        OnPointerClick();
        OnPointerDrag();
        OnPointerUp();
    }

    // .. 레이케스트하여 얻은 첫번째 UI에서 컴포넌트 찾아 리턴
    private T RaycastAndGetFirstComponent<T>() where T : Component
    {
        rrList.Clear();

        gr.Raycast(ped, rrList);

        if (rrList.Count == 0)
            return null;

        return rrList[0].gameObject.GetComponent<T>();
    }

    // .. 슬롯 클릭 이벤트(드래그 및 아이템 사용)
    private void OnPointerClick()
    {
        // .. 좌클릭(드래그) 
        if (Input.GetMouseButtonDown(leftClick))
        {
            beginDragSlot = RaycastAndGetFirstComponent<ItemSlotUI>();      

            // .. 아이템이 있는 슬롯일 경우
            if(beginDragSlot != null && beginDragSlot.HasItem && beginDragSlot.IsAccessible)
            {
                // .. 드래그 위치,참조 등록
                beginDragIconTransform = beginDragSlot.IconRect.transform;
                beginDragIconPoint = beginDragIconTransform.position;
                beginDragCursorPoint = Input.mousePosition;

                beginDragSlotSiblingIndex = beginDragSlot.transform.GetSiblingIndex();
                beginDragSlot.transform.SetAsLastSibling();

                beginDragSlot.SetHighlightOnTop(false);
            }
            else
            {
                beginDragSlot = null;
            }
        }
    }

    // .. 드래그 하는 중
    private void OnPointerDrag()
    {
        if (beginDragSlot == null) return;

        if(Input.GetMouseButton(leftClick))
        {
            // .. 슬롯 아이콘 위치 업데이트
            beginDragIconTransform.position = beginDragIconPoint + (Input.mousePosition - beginDragCursorPoint);
        }
    }

    // .. 클릭을 뗄 때
    private void OnPointerUp()
    {
        if(Input.GetMouseButtonUp(leftClick))
        {
            // .. End Drag
            if(beginDragSlot != null)
            {
                // .. 위치 복원시키기
                beginDragIconTransform.position = beginDragIconPoint;

                // .. UI 순서 복원
                beginDragSlot.transform.SetSiblingIndex(beginDragSlotSiblingIndex);

                // .. 드래그 완료 처리
                EndDrag();

                // .. 하이라이트 이미지를 아이콘보다 앞에
                beginDragSlot.SetHighlightOnTop(true);

                // .. 참조 제거
                beginDragSlot = null;
                beginDragIconTransform = null;
            }
        }
    }
  • 마우스 포인터의 Down, Drag, Up 이벤트를 구현해주었습니다.

댓글남기기