Chapter 9-4. 건축 : 건축 아이템 소모

Date:     Updated:

카테고리:

태그:

인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

건축 시스템

🚀 건축 UI 필요한 아이템 텍스트

image

이런식으로 해당 슬롯의 건축물을 건축하기 위해서 필요한 아이템을 표시해줄 것이다. 텍스트 UI 를 슬롯들에 추가해준다.

📜CraftManual.cs

[System.Serializable]
public class Craft
{
    public string craftName; // 이름
    public Sprite craftImage; // 이미지
    public string craftDescription; // 설명
    public string[] craftNeedItem;  // 필요한 아이템
    public int[] craftNeedItemCount; // 필요한 아이템의 개수
    public GameObject go_prefab; // 실제 설치 될 프리팹
    public GameObject go_PreviewPrefab; // 미리 보기 프리팹
}

public class CraftManual : MonoBehaviour
{
    [SerializeField]
    private Text[] text_SlotNeedItem;

필요한 아이템 텍스트도 추가해주자. 필요한 아이템은 여러개일 수 있기 때문에 배열로 선언한다.

  • 필요한 아이템 craftNeedItem 배열
  • 필요한 아이템의 개수 craftNeedItemCount 배열
    • craftNeedItemCount[i]은 craftNeedItem[i] 아이템의 갯수가 들어간다.

이 텍스트를 표시할 4 개의 텍스트 UI 오브젝트들도 배열로 추가해주자.

image

  • 모닥불 건축시 Leaf 3 개, Log 2 개 필요
  • 토대 건축시 Log 2 개 필요
  • 기둥 건축시 Log 1 개 필요
    private void ClearSlot()
    {
        for (int i = 0; i < go_Slots.Length; i++)
        {
            image_Slot[i].sprite = null;
            text_SlotName[i].text = "";
            text_SlotDescription[i].text = "";
            text_SlotNeedItem[i].text = "";
            go_Slots[i].SetActive(false);
        }
    }

    private void TabSlotSetting(Craft[] _craft_tab)
    {
        ClearSlot();

        craft_SelectedTab = _craft_tab;

        int startSlotNumber = (page - 1) * go_Slots.Length; // 4 의 배수

        for (int i = startSlotNumber; i < craft_SelectedTab.Length; i++)
        {
            if (i == page * go_Slots.Length) // 슬롯 4 개 초과하지 않도록
                break;

            go_Slots[i - startSlotNumber].SetActive(true);

            image_Slot[i - startSlotNumber].sprite = craft_SelectedTab[i].craftImage;
            text_SlotName[i - startSlotNumber].text = craft_SelectedTab[i].craftName;
            text_SlotDescription[i - startSlotNumber].text = craft_SelectedTab[i].craftDescription;

            for (int j = 0; j < craft_SelectedTab[i].craftNeedItem.Length; j++)
            {
                text_SlotNeedItem[i - startSlotNumber].text += craft_SelectedTab[i].craftNeedItem[j];
                text_SlotNeedItem[i - startSlotNumber].text += " x " + craft_SelectedTab[i].craftNeedItemCount[j] + "\n";
            }
        }
    }
  • ClearSlot()
    • 아이템 설명 텍스트 text_SlotNeedItem
  • TabSlotSetting(Craft[] _craft_tab)
    • 건축물을 지을 때 필요한 아이템이 여러개일 수 있기 때문에 text_SlotNeedItem에 텍스트 문자열 설정시 for문으로 돌려야 한다.
      아이템이 3 개라면
      
      통나무 x 10
      나뭇가지 x 5
      나뭇잎 x 2
      
      이렇게 3 줄로 나뉜 하나의 텍스트로서 들어가야 함.
      
              for (int j = 0; j < craft_SelectedTab[i].craftNeedItem.Length; j++)
              {
                  text_SlotNeedItem[i - startSlotNumber].text += craft_SelectedTab[i].craftNeedItem[j];
                  text_SlotNeedItem[i - startSlotNumber].text += " x " + craft_SelectedTab[i].craftNeedItemCount[j] + "\n"; // 한 줄 띄우기
              }
      

image

4 개의 필요한 아이템 텍스트 UI 오브젝트도 text_SlotNeedItem 배열에 할당해주기


🚀 건축 아이템 소모 처리

건축하면 그 건축할 때 소모되는 아이템을 인벤토리 혹은 퀵슬롯에 있는 아이템에서 차감해주어야 한다. 따라서 📜Inventory.cs 에서 public 함수를 만들어 적절하게 이를 호출할 수 있도록 함

📜Inventory.cs

    public int GetItemCount(string _itemName)
    {
        int temp = SearchSlotItem(slots, _itemName);
        return temp != 0 ? temp : SearchSlotItem(quickSlots, _itemName);
    }

    private int SearchSlotItem(Slot[] _slots, string _itemName)
    {
        for (int i = 0; i < _slots.Length; i++)
        {
            if (_slots[i].item != null)
            {
                if (_itemName == _slots[i].item.itemName)
                    return _slots[i].itemCount;
            }
        }

        return 0;
    }

    public void SetItemCount(string _itemName, int _itemCount)
    {
        if (!ItemCountAdjust(slots, _itemName, _itemCount))
            ItemCountAdjust(quickSlots, _itemName, _itemCount);
    }

    private bool ItemCountAdjust(Slot[] _slots, string _itemName, int _itemCount)
    {
        for (int i = 0; i < _slots.Length; i++)
        {
            if (_slots[i].item != null)
            {
                if (_itemName == _slots[i].item.itemName)
                {
                    _slots[i].SetSlotCount(-_itemCount);
                    return true;
                }
            }
        }
        return false; // 인벤토리에 없어서 퀵슬롯에서 빼야 됨
    }
  • 먼저 현재 인벤토리 혹은 퀵슬롯에서 가지고 있는 아이템 갯수가 해당 건축물에 필요한 아이템 갯수보다 작으면 프리뷰를 생성하지 못하게 해야 한다. 즉 건축 슬롯 눌러도 건축 되지 않게끔 해야 한다. 따라서 인수로 받은 아이템이 현재 인벤토리 혹은 퀵슬롯에 몇개 있는지 확인해야 한다.
    • GetItemCount
      • 인수로 받은 아이템 이름과 일치하는 아이템이 인벤토리 혹은 퀵슬롯에 있다면 그 갯수를 리턴한다. 없다면 0 리턴
        • 인벤토리 슬롯들에서 검사를 진행하고 SearchSlotItem(slots, _itemName)
        • 없다면 SearchSlotItem(quickSlots, _itemName) 퀵슬롯 슬롯들에서 한번 더 검사 진행
    • SearchSlotItem
      • 인수로 받은 슬롯 배열에서 인수로 받은 이름과 일치하는 아이템을 찾는다.
      • 찾았다면 그 아이템의 현재 갯수 리턴
      • 없다면 0 리턴
  • 건축물을 지었다면 인벤토리 혹은 퀵슬롯에서 보유중인 아이템 갯수에서 차감 처리를 해야 한다. 건축에 쓰인 갯수만큼!
    • SetItemCount
      • 인벤토리 슬롯들에서 검사를 진행하고 ItemCountAdjust(slots, _itemName, _itemCount) 없다면 ItemCountAdjust(quickSlots, _itemName, _itemCount) 퀵슬롯 슬롯들에서 한번 더 검사 진행
    • ItemCountAdjust
      • 인수로 받은 슬롯 배열에서 인수로 받은 이름과 일치하는 아이템을 찾는다.
      • 찾았다면 그 아이템의 보유 갯수를 인수로 받은 _itemCount 만큼 차감하고 true 리턴
      • 못 찾았다면 false 리턴


📜CraftManual.cs

    // 필요한 컴포넌트
    private Inventory theInventory;

    void Start()
    {
        theInventory = FindObjectOfType<Inventory>();

        tabNumber = 0;
        page = 1;
        TabSlotSetting(craft_fire);
    }

📜Inventory 를 컴포넌트로 가져온다. 위에서 만든 public 함수들을 사용하기 위해서.

    public void SlotClick(int _slotNumber)
    {
        selectedSlotNumber = _slotNumber + (page - 1) * go_Slots.Length;

        if (!CheckIngredient())
            return;

        go_Preview = Instantiate(craft_SelectedTab[selectedSlotNumber].go_PreviewPrefab, tf_Player.position + tf_Player.forward, Quaternion.identity);
        go_Prefab = craft_SelectedTab[selectedSlotNumber].go_prefab;
        isPreviewActivated = true;
        go_BaseUI.SetActive(false);
    }

    private bool CheckIngredient()
    {
        for (int i = 0; i < craft_SelectedTab[selectedSlotNumber].craftNeedItem.Length; i++)
        {
            if (theInventory.GetItemCount(craft_SelectedTab[selectedSlotNumber].craftNeedItem[i]) < craft_SelectedTab[selectedSlotNumber].craftNeedItemCount[i])
                return false;
        }

        return true;
    }

    private void UseIngredient()
    {
        for (int i = 0; i < craft_SelectedTab[selectedSlotNumber].craftNeedItem.Length; i++)
        {
            theInventory.SetItemCount(craft_SelectedTab[selectedSlotNumber].craftNeedItem[i], craft_SelectedTab[selectedSlotNumber].craftNeedItemCount[i]);
        }
    }

    private void Build()
    {
        if(isPreviewActivated && go_Preview.GetComponent<PreviewObject>().isBuildable())
        {
            UseIngredient();

            Instantiate(go_Prefab, go_Preview.transform.position, go_Preview.transform.rotation);
            Destroy(go_Preview);
            isActivated = false;
            isPreviewActivated = false;
            go_Preview = null;
            go_Prefab = null;
        }
    }
  • SlotClick
    • 현재 보유 아이템으로 클릭한 슬롯의 건축물을 지을 수 없다면 프리뷰를 짓지 못한다. if (!CheckIngredient()) return;
  • CheckIngredient()
    • 현재 선택된 탭의 선택된 슬롯이 필요한 아이템들은 여러개가 있을 수 있으므로 for문 돌려 다 검사
      • 아이템 하나라도 갯수 모자르면 건축 못한다.
      • 현재 선택된 탭의 선택된 슬롯이 필요한 아이템의 갯수보다 현재 보유 중인 아이템 갯수가 더 작으면 건축하지 못한다. false 리턴
        • 📜Inventory의 GetItemCount 함수 사용
  • UseIngredient()
    • 건축시 실제 건축물에 필요한 아이템들의 인벤토리or퀵슬롯 차감 처리.
      • 📜Inventory의 SetItemCount 함수 사용
  • Build()
    • 건축시 UseIngredient() 호출하여 아이템 차감

image



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 3 카테고리 내 다른 글 보러가기

댓글 남기기