2 분 소요

Intro

이번 포스팅에서는 인벤토리에서 마우스 드래그&드롭으로 아이템을 옮기거나 다른 슬롯의 아이템과 자리를 바꾸는 기능을 추가했습니다.

image


ItemSlotUI 클래스

슬롯에서 처리해야할것은 아이템 아이콘의 위치변경 처리입니다.

    private string iconName = "";     // 현재 아이템 아이콘 이름

    // 슬롯에 아이템 아이콘 등록
    public void SetItemIcon(string itemSprite)
    {
        if(itemSprite != null)
        {
            // 아이콘 데이터 가져오기
            ResourceManager.Instance.LoadIcon(itemSprite, sprite =>
            {
                // 성공
                if (sprite != null)
                {
                    // 아이콘 이름 저장
                    iconName = itemSprite;
                    // 아이콘 설정
                    iconImage.sprite = sprite;
                    ShowIcon();
                }
                else
                {
                    Debug.Log($"Failed to load icon for item : {itemSprite}");
                }
            });
        }
        else
        {
            RemoveItemIcon();
        }
    }

    // 다른 슬롯으로 아이템 이동
    public void SwapOrMoveIcon(ItemSlotUI otherSlot)
    {
        // 1. 다른 슬롯이 지정되지 않았을 때
        if (otherSlot == null) return;
        // 2. 자기 자신일 때
        if (otherSlot == this) return;
        // 3. 비활성화 상태일 때
        if (!this.IsAccessible || !otherSlot.IsAccessible) return;

        // 1. 다른 슬롯에 아이템이 있을 때 -> 내 아이콘은 다른 슬롯의 아이콘으로 변경
        if (otherSlot.HasItem) SetItemIcon(otherSlot.iconName);
        // 2. 다른 슬롯에 아이템이 없을 때 -> 내 아이콘만 지우기
        else RemoveItemIcon();

        otherSlot.SetItemIcon(iconName);
    }


  • 슬롯의 현재 아이콘 이름을 저장할 itemName 를 추가했습니다.
    • 따라서 아이콘이 등록될 때 아이콘 이름도 함께 저장되도록 했습니다.
  • SwapOrMoveIcon 함수는 이동할 다른 슬롯의 정보를 매개변수로 받습니다.
    • 다른 슬롯이 지정되지 않았거나, 자신과 자신, 비활성화 슬롯간의 교환은 무시합니다.
    • 빈 슬롯으로 이동할 때는 현재 내 슬롯을 비우고 빈 슬롯에 내 아이콘을 등록합니다.
    • 다른 슬롯에 아이템이 있을 때 내 슬롯은 다른 슬롯의 아이콘으로 변경합니다.

InventoryUI 클래스

InventoryUI 클래스에서는 마우스 이벤트의 처리를 구현합니다.

    // 마우스 드래그 종료 처리(아이템 수량 나누기, 교환, 이동, 버리기 등)
    private void EndDrag()
    {
        ItemSlotUI endDragSlot = RaycastAndgetFirstComponent<ItemSlotUI>();

        // 아이템 이동 및 교환
        if(endDragSlot != null && endDragSlot.IsAccessible)
        {
            TrySwapItems(beginDragSlot, endDragSlot);
        }
    }

    // 두 슬롯 아이템 교환
    public void TrySwapItems(ItemSlotUI begin, ItemSlotUI end)
    {
        // 자기자신 처리
        if (begin == end) return;

        begin.SwapOrMoveIcon(end);
        inventory.Swap(begin.Index, end.Index);
    }


  • 마우스 이벤트 처리는 EndDrag 함수에서 처리합니다.
    • 드래그하는 슬롯 정보를 가져와 TrySwapItems 함수를 호출합니다.
  • TrySwapItems 함수는 ItemSlotUI의 SwapOrMoveIcon 함수를 호출하여 아이콘 위치를 변경합니다.
    • 그 다음 Inventory 클래스의 Swap 함수를 호출합니다.

Inventory 클래스

Inventory 클래스에서는 실질적인 아이템 데이터의 교환이 이루어집니다.

    // 인벤토리에 아이템 추가해보기(임시)
    private void InitTest()
    {
        int testItem01 = 1001;

        for(int i = 0; i<2;i++)
        {
            int id = testItem01 + i;

            WeaponItemData weaponData = DataManager.Instance.GetDataById(id);

            // 업 캐스팅(WeaponItemData => ItemData)
            ItemDataArray[i] = weaponData;

            // 다운 캐스팅
            if (ItemDataArray[i] is WeaponItemData)
                AddItem(ItemDataArray[i]);
        }
    }

    // 인덱스 슬롯 갱신(여러 개의 슬롯) Overloading
    private void UpdateSlot(params int[] indices)   // index의 복수형
    {
        foreach(var i in indices)
        {
            UpdateSlot(i);
        }
    }

    // 두 슬롯 아이템 스왑
    public void Swap(int beginIndex, int endIndex)
    {
        // 접근불가 슬롯 처리
        if (!IsValidIndex(beginIndex) || !IsValidIndex(endIndex)) return;

        Item itemA = items[beginIndex];
        Item itemB = items[endIndex];

        // 아이템 위치 변경
        items[beginIndex] = itemB;
        items[endIndex] = itemA;

        // 슬롯 갱신
        UpdateSlot(beginIndex, endIndex);
    }


  • 먼저 테스트를 위해 두개의 아이템을 인벤토리에 추가했습니다.(지난번엔 한 개)
  • 아이템 데이터의 교환은 Swap 함수에서 처리됩니다.
    • 두 아이템 위치를 변경한 뒤 슬롯을 갱신했습니다.
  • 여러개 슬롯의 갱신을 위해 UpdateSlot 함수를 Overloading 했습니다.
    • index의 복수형은 indexes도 맞지만 개발쪽에선 indices 라고 사용한다고 합니다…(왜?)

댓글남기기