유니티 RPG - 14. 인벤토리-2(아이템 슬롯 구현)
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 에서 호출하여 사용합니다.
- InventoryUI 에서 호출하여 사용합니다.
- 하이라이트 효과는 코루틴을 사용해서 구현하였습니다
- 슬롯에 마우스를 올리면 HighlightFadeIn 함수가 호출되어 하이라이트 이미지의 알파값을 0에서 0.5까지 0.2초에 걸쳐 증가시킵니다.
- 슬롯에서 마우스를 뗄 때 HighlightFadeOut 함수가 호출되어 HighlightFadeIn의 반대 작업이 수행됩니다.
- 하이라이트 효과는 InventoryUI 에서 마우스 이벤트가 발생할 때 Highlight() 함수를 호출하여 활성화시킵니다.
다음 포스팅에서는 InventoryUI 클래스에 마우스 이벤트를 추가하여 작성된 ItemSlotUI가 제대로 동작하는지 확인해보겠습니다.
댓글남기기