4 분 소요

Intro

이번 포스팅에서는 인벤토리 시스템에서 필요한 여러 기능들을 추가했습니다.

아래는 인벤토리 시스템에서 필요한것들을 생각나는대로 나열한것입니다.


먼저 인벤토리에 있는 각 슬롯이 관리해야할것들입니다.

  • ItemSlotUI(각 아이템 슬롯)
    • 슬롯의 인덱스 : 이 슬롯이 몇번째 슬롯인지
    • 아이템 이미지 : 이 슬롯에 표시할 아이템의 이미지
    • 아이템 수량 텍스트 : 이 슬롯에 있는 아이템의 수량
    • 접근 가능한 슬롯인지 여부
      • 보통 게임에서 인벤토리 용량을 늘리려면 돈주고 사야됨
      • 따라서 처음부터 모든 인벤토르 슬롯이 활성화되어있지 않도록할 것.
    • 하이라이트 이미지 : 슬롯에 마우스를 올렸을 때 강조될 이미지

다음으로 인벤토리 시스템 자체가 관리해야할것들입니다.

  • Inventory(인벤토리 시스템)
    • 아이템 정보 확인 및 인벤토리 갱신
    • 아이템 추가 : 인벤토리에 아이템 추가
    • 아이템 제거 : 인벤토리에 아이템 제거
    • 아이템 이동 : 인벤토리 내에서 마우스 드래그앤드롭으로 아이템 위치 이동
    • 아이템 정렬 : 특정 기준으로 인벤토리내의 아이템 정렬
    • 아이템 사용 : 사용가능한 아이템을 사용


InventoryUI 클래스는 인벤토리의 틀이고, 그 안에 개별 ItemSlotUI들이 존재합니다.

인벤토리에서 필요한 기능들은 Inventory 클래스가 담당합니다.

따라서 ItemSlotUI에서 필요한 Item의 공유는 InventoryUI, Inventory에 의해 간접적으로 이루어지도록 하였습니다.

ItemSlotUI

슬롯에서 필요한 멤버 변수들입니다.

    [SerializeField] private Image iconImage;           // 아이템 아이콘(이미지)
    [SerializeField] private Text amountText;           // 아이템 수량
    [SerializeField] private Image highlightImage;      // 하이라이트 이미지
    
    private Image slotImage;
    private InventoryUI inventoryUI;

    private RectTransform slotRect;                     // 슬롯의 RT
    private RectTransform iconRect;                     // 슬롯의 아이템 아이콘 RT
    private RectTransform highlightRect;                // 슬롯의 하이라이트 RT

    private GameObject iconGo;                          
    private GameObject textGo;
    private GameObject highlightGo;


    private float padding = 1f;                         // 슬롯 내 아이콘과 슬롯 사이 여백
    private float maxHighlightAlpha = 0.5f;             // 하이라이트 이미지 알파값
    private float currentHighlightAlpha = 0f;           // 현재 하이라이트 이미지 알파값
    private float highlightFadeDuration = 0.2f;         // 하이라이트 소요 시간

    private bool isAccessibleSlot = true;               // 슬롯 접근가능 여부
    private bool isAccessibleItem = true;               // 아이템 접근가능 여부

    // 비활성화된 슬롯 색상
    private Color InAccessibleSlotColor = new Color(0.2f, 0.2f, 0.2f, 0.5f);
    // 비활성화된 아이콘 색상
    private Color InAccessibleIconColor = new Color(0.5f, 0.5f, 0.5f, 0.5f);
       
    #region ** PROPERTIES **
    public int Index { get; private set; }              // 슬롯 인덱스
    public bool HasItem => iconImage.sprite != null;    // 슬롯에 아이템이 있는지 여부(sprite 여부로 확인)

    public bool IsAccessible => isAccessibleItem && isAccessibleSlot;

    public RectTransform SlotRect => slotRect;

    public RectTransform IconRect => iconRect;
    #endregion



아래는 슬롯에 표시될 아이템의 아이콘, 하이라이트 이미지의 정보를 가져오고 세팅해주는 함수입니다.

private void Awake()
    {
        InitComponents();
        InitValues();
    }

    // 초기화
    private void InitComponents()
    {
        inventoryUI = GetComponentInParent<InventoryUI>();

        slotRect = GetComponent<RectTransform>();
        iconRect = iconImage.rectTransform;
        highlightRect = highlightImage.rectTransform;

        iconGo = iconRect.gameObject;
        textGo = amountText.gameObject;
        highlightGo = highlightImage.gameObject;

        slotImage = GetComponent<Image>();
    }

    // 초기화
    private void InitValues()
    {
        // 아이콘 RT 설정(Pivot : 중앙, Anchor : Top Left)
        iconRect.pivot = new Vector2(0.5f, 0.5f);
        iconRect.anchorMin = Vector2.zero;
        iconRect.anchorMax = Vector2.one;

        // 아이콘 패딩 설정
        iconRect.offsetMin = Vector2.one * (padding);
        iconRect.offsetMax = Vector2.one * (-padding);

        // 아이콘과 하이라이트 RT를 동일하게 설정
        highlightRect.pivot = iconRect.pivot;
        highlightRect.anchorMin = iconRect.anchorMin;
        highlightRect.anchorMax = iconRect.anchorMax;
        highlightRect.offsetMin = iconRect.offsetMin;
        highlightRect.offsetMax = iconRect.offsetMax;

        // 아이콘 및 하이라이트 이미지는 클릭X
        iconImage.raycastTarget = false;
        highlightImage.raycastTarget = false;

        HideIcon();
        // 하이라이트 효과 꺼놓기
        highlightGo.SetActive(false);
    }



아래는 슬롯에서 필요한 몇가지 메서드들입니다.

    // 아이템 아이콘 활성화
    private void ShowIcon() => iconGo.SetActive(true);
    
    // 아이템 아이콘 비활성화
    private void HideIcon() => iconGo.SetActive(false);
   
    // 수량 텍스트 활성화
    private void ShowText() => textGo.SetActive(true);
    
    // 수량 텍스트 비활성화
    private void HideText() => textGo.SetActive(false);

    // 슬롯 인덱스 설정
    public void SetSlotIndex(int index) => Index = index;
 
    // 슬롯 활성화/비활성화 여부 설정
    public void SetSlotAccessibleState(bool value)
    {
        // 현재 슬롯상태가 설정하고자하는 value와 같으면 무시
        if (isAccessibleSlot == value) return;

        // 활성화된 슬롯
        if(value)
        {
            slotImage.color = Color.black;
        }
        // 비활성화된 슬롯
        else
        {
            slotImage.color = InAccessibleSlotColor;
            HideIcon();
            HideText();
        }

        isAccessibleSlot = value;
    }

    // 아이템 활성화/비활성화 여부 설정
    public void SetItemAccessibleState(bool value)
    {
        // 현재 아이템상태가 설정하고자하는 value와 같으면 무시
        if (isAccessibleItem == value) return;

        // 활성화된 아이템 색상
        if(value)
        {
            iconImage.color = Color.white;
            amountText.color = Color.white;
        }
        // 비활성화된 아이템 색상
        else
        {
            iconImage.color = InAccessibleIconColor;
            amountText.color = InAccessibleIconColor;
        }

        isAccessibleItem = value;
    }

    // .. 하이라이트 이미지를 아이콘 이미지 상/하단으로 표시
    public void SetHighlightOnTop(bool value)
    {
        if (value)
            highlightRect.SetAsLastSibling();
        else
            highlightRect.SetAsFirstSibling();
    }

    // 슬롯 하이라이트 표시 및 해제
    public void Highlight(bool show)
    {
        if (show)
            StartCoroutine(nameof(HighlightFadeIn));
        else
            StartCoroutine(nameof(HighlightFadeOut));
    }

    // 하이라이트 Fade-in
    private IEnumerator HighlightFadeIn()
    {
        // 실행중인 fade-out 멈추기
        StopCoroutine(nameof(HighlightFadeOut));

        // 하이라이트 이미지 활성화
        highlightGo.SetActive(true);

        float timer = maxHighlightAlpha / highlightFadeDuration;

        // 하이라이트 이미지 알파값을 서서히 증가시키기
        for(; currentHighlightAlpha <= maxHighlightAlpha; currentHighlightAlpha += timer * Time.deltaTime)
        {
            highlightImage.color = new Color(
                     highlightImage.color.r,
                     highlightImage.color.g,
                     highlightImage.color.b,
                     currentHighlightAlpha
                );

            yield return null;
        }
    }

    // 하이라이트 Fade-out
    private IEnumerator HighlightFadeOut()
    {
        StopCoroutine(nameof(HighlightFadeIn));

        float timer = maxHighlightAlpha / highlightFadeDuration;

        // 하이라이트 이미지 알파값을 서서히 감소시키기
        for(; currentHighlightAlpha >= 0f; currentHighlightAlpha -= timer * Time.deltaTime)
        {
            highlightImage.color = new Color(
                     highlightImage.color.r,
                     highlightImage.color.g,
                     highlightImage.color.b,
                     currentHighlightAlpha
                );

            yield return null;
        }
        highlightGo.SetActive(false);
    }


  • 아이템 아이콘 및 텍스트를 On/Off 하는 함수를 구현하였습니다.

  • 아이템 및 슬롯의 활성/비활성화 하는 함수를 구현하였습니다.
    • InventoryUI 에서 호출하여 사용합니다.
  • 하이라이트 효과는 코루틴을 사용해서 구현하였습니다
    • 슬롯에 마우스를 올리면 HighlightFadeIn 함수가 호출되어 하이라이트 이미지의 알파값을 0에서 0.5까지 0.2초에 걸쳐 증가시킵니다.
    • 슬롯에서 마우스를 뗄 때 HighlightFadeOut 함수가 호출되어 HighlightFadeIn의 반대 작업이 수행됩니다.
  • 하이라이트 효과는 InventoryUI 에서 마우스 이벤트가 발생할 때 Highlight() 함수를 호출하여 활성화시킵니다.



다음 포스팅에서는 InventoryUI 클래스에 마우스 이벤트를 추가하여 작성된 ItemSlotUI가 제대로 동작하는지 확인해보겠습니다.

댓글남기기