(출처 : https://rito15.github.io/posts/unity-study-rpg-inventory/)
위에 링크에 있는 내용을 바탕으로 제작했다.
우선 인벤토리를 제작하기 전에 인벤토리에 들어갈 SlotPrefab을 만든 후 Slot에 들어갈 SlotUI Script를 만든다.
SlotPrefab - Hierarchy
구조는 Background Image와 ItemIconImage 그리고 포션 같이 셀 수 있는 아이템이 있는 경우 숫자를 표시해주기 위해서 Text를 넣어주고 셀 수 있는 아이템인 경우 활성화 시켜준다.
HighlightImage는 커서가 Item Slot 위에 있을 때 활성화 시켜주기 위한 용도이다.
SlotUI.cs
// 슬롯 내에서 아이콘과 슬롯 사이의 여백
[SerializeField] private float padding = 1f;
// 아이템 아이콘 이미지
[SerializeField] private Image iconImage;
// 아이템 개수 텍스트
[SerializeField] private TextMeshProUGUI amountText;
// 슬롯에 마우스가 있을 때 나타나는 하이라이트 이미지
[SerializeField] private Image highlightImage;
// 하이라이트 이미지 알파 값
[SerializeField] private float highlighAlpha = 0.5f;
// 하이라이트 소요 시간
[SerializeField] private float highlightFadeDuration = 0.2f;
우선 위에 용도에 맞게 사용하기 위해서 IconImage, Text, HighlightImage를 가져와준다.
// Slot을 생성할 때 Index에 값을 넣어줘서 사용
public void SetSlotIndex(int slotIndex) => Index = slotIndex;
public int Index { get; private set; }
// 슬롯이 아이템을 보유하고 있는지 여부를 sprite로 확인
public bool HasItem => iconImage.sprite != null;
// 접근 가능한 슬롯인지 여부 확인
public bool IsAccessible => isAccessibleSlot && isAccessibleItem;
public RectTransform SlotRect => slotRect;
public RectTransform IconRect => iconRect;
private RectTransform slotRect;
private RectTransform iconRect;
private RectTransform highlightRect;
private GameObject iconGo;
private GameObject textGo;
private GameObject highlightGo;
private Image slotImage;
private float currentHLAlpa = 0f;
private bool isAccessibleSlot = true;
private bool isAccessibleItem = true;
private bool isNotEqualEquipmentSlot = false;
private static readonly Color InaccessibleSlotColor = new Color(0.2f, 0.2f, 0.2f, 0.5f);
private static readonly Color InaccessibleIconColor = new Color(0.5f, 0.5f, 0.5f, 0.5f);
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 변수로 사용하면서 => 람다식으로 사용하는 경우는 private 변수 값을 직접적으로 접근해서 사용하지 못하게 끔 하기 위해서 그렇게 구현한 것 같다.
private void InitComponents()
{
// Rects
slotRect = GetComponent<RectTransform>();
iconRect = iconImage.rectTransform;
highlightRect = highlightImage.rectTransform;
// GameObjects
iconGo = iconRect.gameObject;
textGo = amountText.gameObject;
highlightGo = highlightImage.gameObject;
// Images
slotImage = GetComponent<Image>();
}
private void InitValue()
{
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);
// icon 과 highlight 크기 동일하도록 설정
highlightRect.pivot = iconRect.pivot;
highlightRect.anchorMin = iconRect.anchorMin;
highlightRect.anchorMax = iconRect.anchorMax;
highlightRect.offsetMin = iconRect.offsetMin;
highlightRect.offsetMax = iconRect.offsetMax;
// Image
iconImage.raycastTarget = false;
highlightImage.raycastTarget = false;
// Icon
HideIcon();
highlightGo.SetActive(false);
}
Awake 함수에서 호출해주는 초기화 함수들이다.
// 슬롯 자체의 활성화 / 비활성화 여부 설정
public void SetSlotsAccessibleState(bool value)
{
// 중복 처리 지양
if (isAccessibleSlot == value) return;
if (value)
{
slotImage.color = Color.black;
}
else
{
slotImage.color = InaccessibleSlotColor;
HideIcon();
HideText();
}
isAccessibleSlot = value;
}
// 아이템 활성화 / 비활성화 여부 설정
public void SetItemAccessibleState(bool value)
{
if (isAccessibleItem == value) return;
if (value)
{
iconImage.color = Color.white;
amountText.color = Color.white;
}
else
{
iconImage.color = InaccessibleIconColor;
amountText.color = InaccessibleIconColor;
}
isAccessibleItem = value;
}
Slot들을 만들어두고서 일정 부분을 비활성화 하고 싶을 때, 또 비활성화 해둔 부분을 다시 활성화 해줄 때 사용할 수 있다.
나중에 Inventory UI에서 연결해서 사용할 예정이다. 그리고 아이템 또한 활성화 / 비활성화 여부를 설정할 수 있게 끔 만들었지만 난 사용하지 않았다.
// InventoryUIDragAndDrop.cs에서 사용될 함수
public void SwapOrMoveIcon(ItemSlotUIs other)
{
if (other == null || other == this) return;
if (!this.IsAccessible || !other.IsAccessible) return;
// 현재 Icon Image를 저장해둠
var temp = iconImage.sprite;
// 드랍한 곳에 아이템이 있는 경우 : 교환
if (other.HasItem)
SetItem(other.iconImage.sprite);
// 없는 경우 : 이동
else
RemoveItem();
// 교환한 곳에 Icon Image를 현재 Icon Image로 전환
other.SetItem(temp);
other.SetEquipmentItemData(data);
}
// InventoryUI.cs에서도 사용될 함수
public void SetItem(Sprite itemSprite)
{
if (itemSprite != null)
{
iconImage.sprite = itemSprite;
ShowIcon();
}
else
RemoveItem();
}
// InventoryUI.cs에서도 사용될 함수
public void RemoveItem()
{
iconImage.sprite = null;
HideIcon();
HideText();
}
나중에 InventoryUIDragAndDrop.cs 에서 Slot에 아이템을 Drag And Drop 할 때 사용할 함수이다.
함수에서 매개변수로 받는 other는 Drop하는 위치에 ItemSlotUIs이다.
// InventoryUIDragAndDrop.cs에서 사용할 함수
public void Highlight(bool show)
{
if (!this.IsAccessible) return;
if (show)
FadeIn();
else
FadeOut();
void FadeIn()
{
while (true)
{
highlightGo.SetActive(true);
float unit = highlighAlpha / highlightFadeDuration;
for (; currentHLAlpa <= highlighAlpha; currentHLAlpa += unit * Time.deltaTime)
{
highlightImage.color = new Color(highlightImage.color.r, highlightImage.color.g, highlightImage.color.b, currentHLAlpa);
}
break;
}
}
void FadeOut()
{
while (true)
{
float unit = highlighAlpha / highlightFadeDuration;
for (; currentHLAlpa >= 0; currentHLAlpa -= unit * Time.deltaTime)
{
highlightImage.color = new Color(highlightImage.color.r, highlightImage.color.g, highlightImage.color.b, currentHLAlpa);
}
highlightGo.SetActive(false);
break;
}
}
}
public void SetHighlightOnTop(bool value)
{
if (value)
highlightRect.SetAsLastSibling();
else
highlightRect.SetAsFirstSibling();
}
// InventoryUI에서 사용할 함수
public void SetItemAmount(int amount)
{
if (HasItem && amount > 1)
ShowText();
else
HideText();
amountText.text = amount.ToString();
}
- Highlight 함수
IsAccessible은 아까 위에서 Slot과 Item에 활성화 / 비활성화 여부에 따라서 변경되게 된다.
원래 기존 코드에서는 Coroutine으로 FadeIn과 FadeOut 함수 부분을 수행했지만 딱히 별 차이점을 못 느끼겠어서 그냥 while로 수정해뒀다.
만약에 while로 사용할 것이라면 굳이 저렇게 쓰기보다는 아래와 같이 한 줄로 사용하는 것이 좋을 것 같다.
highlightImage.color = new Color(highlightImage.color.r, highlightImage.color.g, highlightImage.color.b, highlighAlpha);
- SetHighlightOnTop 함수
뒤에 SetAsLastSibiling과 SetAsFirstSibling은 Transform이나 RectTransform에서 사용할 수 있는 함수이다.
Hierarchy 창에서 순서를 바꿔줘 HighlightImage UI가 보이거나 보이지 않게 만들어 줄 수 있다.
'내배켐 Unity TIL' 카테고리의 다른 글
Unity 60일차 TIL - Unity (Graphic RayCaster) (0) | 2024.07.05 |
---|---|
Unity 59일차 TIL - Unity (2D ItemInventory2_InventoryUI) (0) | 2024.07.04 |
Unity 57일차 TIL - Unity (C# Class 상속) (0) | 2024.07.02 |
Unity 56일차 TIL - Unity FSM(디자인 패턴) 트러블슈팅 (0) | 2024.07.01 |
Unity 55일차 TIL - Unity FSM(디자인 패턴) (0) | 2024.06.28 |