인벤토리
오늘은 Unity에서 인벤토리 시스템을 구현한 내용들을 정리해보겠습니다. 특히 아이템 획득 UI, 인벤토리 슬롯 관리, 드래그 앤 드롭 기능을 구현하면서 얻은 경험을 공유합니다.
1. 아이템 데이터 구조 설계
public class ItemData { public int Id {get; private set;} public string Name {get; private set;} public string Description {get; private set;} public string PrefabPath {get; private set;} public Sprite Icon {get; private set;} public bool CanStack {get; private set;} public int MaxStack {get; private set;} public EItemType ItemType {get; private set;} public EEquipType EquipType {get; private set;} }
- 아이템 데이터는 읽기 전용 속성으로 설계하여 데이터 무결성을 보장
- 스택 가능 여부와 최대 스택 수를 명시적으로 관리
- 아이템 타입과 장비 타입을 enum으로 정의하여 타입 안전성 확보
2. 아이템 획득 UI 애니메이션 구현
public class ItemPickupUI : PopupUI { [SerializeField] private Image itemIcon; [SerializeField] private TextMeshProUGUI itemName; [SerializeField] private Transform panel; protected override void Awake() { base.Awake(); Managers.UserData.Inventory.onAddItem += Setup; } private void Setup(ItemData data) { Managers.UI.ShowPopupUI(this); itemIcon.sprite = data.Icon; itemName.text = data.Name; // 기존에 panel에 적용된 모든 트윈을 종료 panel.DOKill(); panel.DOScale(1.2f, 0.2f).SetEase(Ease.InOutSine).OnComplete(() => { DOVirtual.DelayedCall(0.5f, () => { panel.DOScale(1f, 0.2f).SetEase(Ease.InOutSine).OnComplete(() => { Managers.UI.ClosePopupUI(this); }); }); }); } }
- DOTween을 사용할 때는 기존 애니메이션을 `DOKill()`로 정리하는 것이 중요
- 애니메이션 체이닝을 통해 자연스러운 시퀀스 구현 가능
- 이벤트 기반 시스템을 활용하여 UI 업데이트 자동화
3. 인벤토리 슬롯 UI 구현
public class ItemSlotUI : MonoBehaviour, IPointerClickHandler { [Header("Background")] [SerializeField] private Color defaultBackground; [SerializeField] private Color weaponBackground; [SerializeField] private Color equipmentBackground; [SerializeField] private Color consumableBackground; [SerializeField] private Color resourceBackground; [SerializeField] private Color placeableBackground; [Header("Info")] [SerializeField] private Image itemIcon; [SerializeField] private Image background; [SerializeField] private TextMeshProUGUI itemAmountText; private Dictionarycolors; public ItemSlot ItemSlot {get; private set;} public void Setup(ItemSlot itemSlot) { ItemSlot = itemSlot; ItemSlot.onChangeStack += UpdateItemSlotUI; UpdateItemSlotUI(itemSlot); onSetup?.Invoke(itemSlot); } }
- Inspector에서 직관적으로 설정할 수 있도록 Header 속성 활용
- 이벤트 기반 업데이트로 성능 최적화
- 아이템 타입별 시각적 구분을 위한 색상 시스템 구현
4. 드래그 앤 드롭 구현
public class MovingSlotUI : PopupUI { [SerializeField] private RectTransform panelRT; [SerializeField] private Image itemImage; [SerializeField] private TextMeshProUGUI itemCountText; public void SetItem(ItemData itemData, int amount) { itemImage.sprite = itemData.Icon; itemCountText.text = amount.ToString(); Vector3 pos = panelRT.parent.InverseTransformPoint(Input.mousePosition); panelRT.localPosition = pos; } private void Update() { Vector3 pos = panelRT.parent.InverseTransformPoint(Input.mousePosition); panelRT.localPosition = pos; } }
- RectTransform을 활용한 UI 요소 위치 조정
- 마우스 위치를 UI 좌표계로 변환하는 방법
- Update 메서드에서 지속적인 위치 업데이트 구현
5. 개선할 점
- 아이템 데이터 캐싱을 통한 성능 최적화
- 드래그 앤 드롭 시 경계 체크 추가
- 아이템 스택 분할 기능 구현
- 인벤토리 정렬 기능 추가
다음에 할 일:
- 아이템 필터링 시스템 구현
- 인벤토리 확장 기능 추가
- 아이템 툴팁 시스템 개선