📁 개발 히스토리

유니티 - 인벤토리 구현하기(6)

일단몸통박치기 2025. 2. 24. 18:22

얼추 그럴듯한 인벤토리가 완성되어간다!

다음은 가볍게 도구 사용하는 모션을 추가해보았당.

 

 

꾹 누르면 작동한다는 것을 설명하기 위해

작은 흰색 원으로 애니메이션 상태를 표기했다.

 

        IV_Item HoldingItem = Inventory.HotbarSlots[Inventory.SelectedSlotIndex].CurrentItem;
        if (Input.GetMouseButton(0) && HoldingItem.Type == IV_Item.ItemType.Tool)
        {
            switch (HoldingItem.Name)
            {
                case "손도끼":
                    PlayerState = PlayerStates.AXE;
                    break;
                case "괭이":
                    PlayerState = PlayerStates.HOE;
                    break;
                case "물뿌리개":
                    PlayerState = PlayerStates.POT;
                    break;
            }

        }

 

간단하게 Player 스크립트에 현재 핫바에 선택된 아이템을 가져와서

도구이고 마우스 클릭이 들어오면 그것을 상태값으로 변경하게끔 했다.

 

 

        switch (PlayerState)
        {
            case PlayerStates.IDLE:
                if (!PlayerAni.GetCurrentAnimatorStateInfo(0).IsName(new string("R_IDLE_" + PlayerSeeing)))
                {
                    PlayerAni.Play(new string("R_IDLE_" + PlayerSeeing));
                }
                ProgressBar.fillAmount = 0;
                break;
            case PlayerStates.WALK:
                if (!PlayerAni.GetCurrentAnimatorStateInfo(0).IsName(new string("R_WALK_" + PlayerSeeing)))
                {
                    PlayerAni.Play(new string("R_WALK_" + PlayerSeeing));
                }
                ProgressBar.fillAmount = 0;
                break;
            case PlayerStates.AXE:
                if (!PlayerAni.GetCurrentAnimatorStateInfo(0).IsName(new string("R_AXE_" + PlayerSeeing)))
                {
                    PlayerAni.Play(new string("R_AXE_" + PlayerSeeing));
                }
                ProgressBar.fillAmount = PlayerAni.GetCurrentAnimatorStateInfo(0).normalizedTime % 1;
                break;
            case PlayerStates.HOE:
                if (!PlayerAni.GetCurrentAnimatorStateInfo(0).IsName(new string("R_HOE_" + PlayerSeeing)))
                {
                    PlayerAni.Play(new string("R_HOE_" + PlayerSeeing));
                }
                ProgressBar.fillAmount = PlayerAni.GetCurrentAnimatorStateInfo(0).normalizedTime % 1;
                break;
            case PlayerStates.POT:
                if (!PlayerAni.GetCurrentAnimatorStateInfo(0).IsName(new string("R_POT_" + PlayerSeeing)))
                {
                    PlayerAni.Play(new string("R_POT_" + PlayerSeeing));
                }
                ProgressBar.fillAmount = PlayerAni.GetCurrentAnimatorStateInfo(0).normalizedTime % 1;
                break;
        }

 

그리고 상태값에 따라 애니메이션을 플레이하는데

ProgressBar.fillAmount를 애니메이션의 normalizedTime로 표기했는데

 

normalizedTime는 애니메이션의 진척도를 0~1로 표현하는 값이지만

반복 애니메이션의 경우 1 이상으로 숫자가 커져버린다.

그래서 1로 나누어 0~1의 값을 반복하도록 한 것.

 

 

 

 

다음은 슬롯을 우클릭하여 아이템을 사용하거나 모두 버리는 기능을 추가했다.

 

 

위 처럼 간단하게 사용과 버리기가 뜨는데

아이템 툴팁 창과 동일하게 Inventory.cs에서 켜고 끄며

슬롯을 우클릭하면 클릭한 자리에 뜨도록 했다.

        UseItemBtn.onClick.AddListener(() =>
        {
            if(InteractSlot.CurrentItem.Type == IV_Item.ItemType.Useable)
            {
                InteractSlot.ReduceCount(1);
                // TO DO : 사용 효과 기재
            }
        });
        DropItemBtn.onClick.AddListener(() =>
        {
            DropItem(InteractSlot, InteractSlot.CurrentItem.Count);
            HideInteractItem();
        });

 

 

 

 

 

마지막으로 아이템 이동!

선택된 아이템을 테두리로 보여주던 것에서

클릭하면 아이템이 마우스에 붙고 다시 클릭해서 아이템을 교체하는 방식으로 수정했다.

 

    // 아이템을 표시해야할지 말지 bool값을 반환
    public bool SwapSlots(IV_Slot Slot)
    {
        // 스왑슬롯박스가 비어있다면 이 슬롯을 저장
        if (SwapSlotBox == null)
        {
            if(Slot.CurrentItem.Num < 0)
            {
                return false;
            }

            SwapSlotBox = Slot;

            PickUpItem.sprite = SwapSlotBox.CurrentItem.Sprite;
            if(SwapSlotBox.CurrentItem.Type == IV_Item.ItemType.Equip || SwapSlotBox.CurrentItem.Type == IV_Item.ItemType.Tool || SwapSlotBox.CurrentItem.Count < 1)
            {
                PickUpItem.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "";
            }
            else
            {
                PickUpItem.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = SwapSlotBox.CurrentItem.Count.ToString();
            }
            PickUpItem.gameObject.SetActive(true);
            return true;
        }
        // 스왑슬롯박스에 동일한 슬롯이 들어있다면 선택 취소
        else if (SwapSlotBox == Slot)
        {
            SwapSlotBox.SetItem(SwapSlotBox.CurrentItem);
            SwapSlotBox = null;

            PickUpItem.gameObject.SetActive(false);
            return false;
        }

        // 두 슬롯의 데이터 교환
        IV_Item tempItem = SwapSlotBox.CurrentItem;

        SwapSlotBox.SetItem(Slot.CurrentItem);
        Slot.SetItem(tempItem);

        SwapSlotBox = null;
        PickUpItem.gameObject.SetActive(false);
        HUDSynchronize();
        return false;
    }

 

 

이 과정에서 슬롯 쪽 마우스 입력도 수정해야했는데

좌클릭으로 실행되는 아이템 스왑과

우클릭으로 실행되는 사용/버리기 창이 중첩되면 안되므로

각 클릭마다 서로 작동중인 부분이 있으면 자동으로 취소하는 것으로 수정!

 

    public void OnPointerClick(PointerEventData eventData)
    { 
        if (eventData.button.Equals(PointerEventData.InputButton.Left))
        {
            // 아이템 사용창부터 끄기
            if(Player.Inventory.InteractSlot != null)
            {
                Player.Inventory.InteractSlot = null;
                Player.Inventory.HideInteractItem();
                return;
            }
            if (Player.Inventory.SwapSlots(this) && IsItemExist)
            {
                // 아이템 픽업
                ItemImg.color = new Color(1, 1, 1, 0);
                ItemCount.text = "";
            }
        }
        else if (eventData.button.Equals(PointerEventData.InputButton.Right))
        {
            // 픽업 중인 아이템 있으면 픽업부터 취소
            if (Player.Inventory.SwapSlotBox != null)
            {
                // 같은 슬롯 한번 더 전송해서 픽업 취소함
                Player.Inventory.SwapSlots(Player.Inventory.SwapSlotBox);
                return;
            }

            // 아이템 사용창 켜기
            Player.Inventory.ShowInteractItem(this);
        }
    }
    
    public void PutBackItem()
    {
        ItemImg.color = new Color(1, 1, 1, 1);

        if (CurrentItem.Type == IV_Item.ItemType.Equip || CurrentItem.Type == IV_Item.ItemType.Tool || CurrentItem.Count < 1)
        {
            ItemCount.text = "";
        }
        else
        {
            ItemCount.text = CurrentItem.Count.ToString();
        }
    }

 

 

PutBackItem은 아이템을 들고 있는 상태에서

인벤토리를 종료하거나 하는 상황에 아이템을 다시 내려놓도록 하는 함수.

 

 

 

 

아주 잘 작동하는 모습!