Chapter 5-5. 인벤토리 : 아이템 회복

Date:     Updated:

카테고리:

태그:

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

Chapter 5. 인벤토리

🚖 포션 아이템 만들기

image

image

이름은 Potion Yellow Item

  • “Item” 태그, 레이어
  • Box Collider
  • Rigidbody
  • 📜ItemPickUp
    • Potion Yellow item 만들어서 할당
      • 아이템 타입은 Used


🚖 포션 먹으면 회복하게 하기

인벤토리에서 해당 포션에 우클릭하면 소모되도록 한다.

📜ItemEffectDatabase.cs

빈 오브젝트 Database를 만들고 📜ItemEffectDatabase.cs 을 붙여 주었다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class ItemEffect
{
    public string itemName;  // 아이템의 이름(Key값으로 사용할 것)
    [Tooltip("HP, SP, DP, HUNGRY, THIRSTY, SATISFY 만 가능합니다.")]
    public string[] part;  // 효과. 어느 부분을 회복하거나 혹은 깎을 포션인지. 포션 하나당 미치는 효과가 여러개일 수 있어 배열.
    public int[] num;  // 수치. 포션 하나당 미치는 효과가 여러개일 수 있어 배열. 그에 따른 수치.
}

public class ItemEffectDatabase : MonoBehaviour
{
    [SerializeField]
    private ItemEffect[] itemEffects;

    private const string HP = "HP", SP = "SP", DP = "DP", HUNGRY = "HUNGRY", THIRSTY = "THIRSTY", SATISFY = "SATISFY";

    [SerializeField]
    private StatusController thePlayerStatus;
    [SerializeField]
    private WeaponManager theWeaponManager;

    public void UseItem(Item _item)
    {
        if (_item.itemType == Item.ItemType.Equipment)
        {
            // 장착
            StartCoroutine(theWeaponManager.ChangeWeaponCoroutine(_item.weaponType, _item.itemName));
        }
        if (_item.itemType == Item.ItemType.Used)
        {
            for (int i = 0; i < itemEffects.Length; i++)
            {
                if (itemEffects[i].itemName == _item.itemName)
                {
                    for (int j = 0; j < itemEffects[i].part.Length; j++)
                    {
                        switch(itemEffects[i].part[j])
                        {
                            case HP:
                                thePlayerStatus.IncreaseHP(itemEffects[i].num[j]);
                                break;
                            case SP:
                                thePlayerStatus.IncreaseStamina(itemEffects[i].num[j]);
                                break;
                            case DP:
                                thePlayerStatus.IncreaseDP(itemEffects[i].num[j]);
                                break;
                            case THIRSTY:
                                thePlayerStatus.IncreaseThirsty(itemEffects[i].num[j]);
                                break;
                            case HUNGRY:
                                thePlayerStatus.IncreaseHungry(itemEffects[i].num[j]);
                                break;
                            case SATISFY:
                                break;
                            default:
                                Debug.Log("잘못된 Status 부위. HP, SP, DP, HUNGRY, THIRSTY, SATISFY 만 가능합니다.");
                                break;
                        }
                        Debug.Log(_item.itemName + " 을 사용했습니다.");
                    }
                    return;
                }
            }
            Debug.Log("itemEffectDatabase에 일치하는 itemName이 없습니다.");
        }
    }
}

  • ItemEffect 클래스 👉 한 아이템의 효과.
    • [System.Serializable]로 선언되어서 이 클래스의 멤버들은 MonoBehaviour 을 상속 받는 클래스가 아닌 일반 C# 클래스임에도 불구하고 유니티 인스펙터에 띄워 여기서 값을 할당할 수 있게 되었다.
    • partnum 의 인덱스는 대응되게 할 것이다. part[2]가 HUNGRY 라면 num[2] 의 원소 값은 HUNGRY 에 대한 수치
    • itemName에 해당하는 하나의 아이템은 part 배열에 속한 부분들에 대한 효과를 가진다. 그에 대응하는 효과 수치는 num 배열에 해당.
  • itemEffects
    • private 으로 선언되었기 때문에 ItemEffect 클래스가 [System.Serializable]긴 하더라도 SerializeField 해주어야 비로소 유니티 인스펙터에 뜨게 된다.
    • 배열이다. 📜ItemEffectDatabase.cs 에서 여러 포션 아이템들을 이 `itemEffects` 배열 멤버에서 한번에 관리 하게 됨.
  • UseItem(Item _item) 아이템 소모시 👉 📜Slot.cs의 우클릭 이벤트에서 처리 했었는데 성능을 위해 이 스크립트로 옮겼다.
    • 아이템이 장비면 장착하고
      • 때문에 📜WeaponManager.cs 가 필요 하다.
        • 다만 Slot과 다르게 Database는 프리팹은 아니기 때문에 FindObejctOfType을 사용하지 않고 직접 할당해주기로 하였다. [SerializeField].
    • 아이템이 소모품이면 👈 포션이 해당 됨
      • 해당 수치에 맞게 효과 적용
        • 인수로 들어온 아이템의 이름이 itemEffects 배열에 있는지를 찾고
        • 찾았다면 해당 아이템의 효과들을 📜StatusController.cs 의 함수들을 호출하여 적용한다.
          • IncreaseHP 등등
        • 모든 효과를 적용했다면 바로 종료. itemEffects 배열에 있는지를 더 찾을 필요가 없으므로.

image

  • Potion Yellow 아이템을 소비 하면
    • SP 가 500 으로 증가하고
    • HUNGRY 가 100 으로 증가하고
    • THIRSTY 가 100 으로 증가하게끔 하였다.


📜Slot.cs

private ItemEffectDatabase theItemEffectDatabase;

    void Start()
    {
        baseRect = transform.parent.parent.GetComponent<RectTransform>().rect;

        theInputNumber = FindObjectOfType<InputNumber>();
        theItemEffectDatabase = FindObjectOfType<ItemEffectDatabase>();
    }

    // 마우스 클릭 이벤트
    public void OnPointerClick(PointerEventData eventData)
    {
        if(eventData.button == PointerEventData.InputButton.Right)
        {
            if (item != null)
            {
                theItemEffectDatabase.UseItem(item);

                if(item.itemType == Item.ItemType.Used)
                    SetSlotCount(-1);
            }
        }
    }
  • Slot은 프리팹이기 때문에 다른 오브젝트를 FindObjectOfType 로 불러올 수 밖에 없다. 또한 20개나 되기 때문에 인벤토리가 활성화 되어 슬롯도 활성화 될 때, Start() 에서 너무 많은 컴포넌트를 로딩한다면 성능에 문제가 생길 것이다.
    • 따라서 📜Slot.cs 의 📜WeaponManager.cs 를 불러오는 부분을 지웠다. 아래 코드를 지우고 위와 같이 고침. 대신 이와 같은 과정은 📜ItemEffectDatabase 에서 하도록 옮겼다.
    • 수정 전 📜Slot.cs
      public void OnPointerClick(PointerEventData eventData)
      {
          if(eventData.button == PointerEventData.InputButton.Right)
          {
              if (item != null)
              {
                  if(item.itemType == Item.ItemType.Equipment) // 👈👈👈👈👈👈👈
                  {
                      // 장착
                      StartCoroutine(theWeaponManager.ChangeWeaponCoroutine(item.weaponType, item.itemName));
                  }
                  else // 👈👈👈👈👈👈👈
                  {
                      // 소비
                      Debug.Log(item.itemName + " 을 사용했습니다.");
                      SetSlotCount(-1);
                  }
              }
          }
      }
      
    • 📜ItemEffectDatabase.cs
      public void UseItem(Item _item)
      {
          if (_item.itemType == Item.ItemType.Equipment) // 👈👈👈👈👈👈👈
          {
              // 장착
              StartCoroutine(theWeaponManager.ChangeWeaponCoroutine(_item.weaponType, _item.itemName));
          }
          if (_item.itemType == Item.ItemType.Used) // 👈👈👈👈👈👈👈
          {
              // 소비
              for (int i = 0; i < itemEffects.Length; i++)
              {
                  if (itemEffects[i].itemName == _item.itemName)
                  {
                      for (int j = 0; j < itemEffects[i].part.Length; j++)
                      {
                          switch(itemEffects[i].part[j])
                          {
                              case HP:
                                  thePlayerStatus.IncreaseHP(itemEffects[i].num[j]);
                                  break;
                              case SP:
                                  thePlayerStatus.IncreaseStamina(itemEffects[i].num[j]);
                                  break;
                              case DP:
                                  thePlayerStatus.IncreaseDP(itemEffects[i].num[j]);
                                  break;
                              case THIRSTY:
                                  thePlayerStatus.IncreaseThirsty(itemEffects[i].num[j]);
                                  break;
                              case HUNGRY:
                                  thePlayerStatus.IncreaseHungry(itemEffects[i].num[j]);
                                  break;
                              case SATISFY:
                                  break;
                              default:
                                  Debug.Log("잘못된 Status 부위. HP, SP, DP, HUNGRY, THIRSTY, SATISFY 만 가능합니다.");
                                  break;
                          }
                          Debug.Log(_item.itemName + " 을 사용했습니다.");
                      }
                      return;
                  }
              }
              Debug.Log("itemEffectDatabase에 일치하는 itemName이 없습니다.");
          }
      }
      
  • 수정 후 📜Slot.cs
    • 무기든 소모품이든, 아이템 사용에 대한 처리를 📜ItemEffectDatabase.cs 의 UseItem 함수에게 전적으로 맡기게 되었다.
      • 대신 해당 아이템이 소모품일 땐 아이템 갯수를 1 감소시키는 처리를 해주었다.
          if(eventData.button == PointerEventData.InputButton.Right)
          {
              if (item != null)
              {
                  theItemEffectDatabase.UseItem(item);
        
                  if(item.itemType == Item.ItemType.Used)
                      SetSlotCount(-1);
              }
          }
        


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

맨 위로 이동하기

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

댓글 남기기