-
유니티 인벤토리 - 인벤토리 시스템Unity 2024. 1. 23. 19:55반응형
안녕하세요
오늘은 유니티 인벤토리 시스템을 만들어 봤습니다.
※ 현재는 클린코드를 지향하고 있지만 인벤토리 시스템을 제작할 당시에는
클린코드 존재를 잘 몰랐던 시기라 보시는데 불편함이 있을 수 있습니다.
[인벤토리 프리팹]
- 인벤토리 프리팹을 만들어 줍니다.
- Inventory 객체에 Inventory.cs를 넣어줍니다.
- ToolTip 객체에 InventorySlotToolTip.cs를 넣어줍니다.
- DragSlot 객체에 DragSlot.cs를 넣어줍니다.
[Inventory.cs]
#region 변수 [Header("=====> 인벤토리 설정 <=====")] [SerializeField] private GameObject InventoryObject; [SerializeField] private GameObject InventoryContent; [SerializeField] private InventorySlotToolTip ToolTip; [SerializeField] private GameObject SlotPrefab; [SerializeField] private Transform ContentArea; [SerializeField] private int SlotCount = 25; public List<ItemData> InventoryItemList = new List<ItemData>(); public InventorySlot[] SlotArray; #endregion // 변수 #region 함수 /** 초기화 */ private void Awake() { InventorySlotCreate(); SlotArray = GetComponentsInChildren<InventorySlot>(); for(int i = 0; i < SlotArray.Length; i++) { SlotArray[i].ToolTip = ToolTip; SlotArray[i].Inven = this; } } /** 인벤토리 활성화 */ public void OpenInventory() => InventoryObject.SetActive(true); /** 인벤토리 비활성화 */ public void CloseInventory() => InventoryObject.SetActive(false); /** 슬롯 생성 */ public void InventorySlotCreate() { for(int i = 0; i < SlotCount; i++) { // 슬롯 생성 var Slot = Instantiate(SlotPrefab, ContentArea); } } /** 아이템을 습득한다 */ public void AcquireItem(ItemData Item, int Count = 1) { for (int i = 0; i < SlotArray.Length; i++) { // 해당 슬롯에 아이템이 있을 경우 if (SlotArray[i].PlusItem != null) { // 해당 슬롯의 아이템 이름을 가져와 습득한 아이템이름과 같은지 확인 if (SlotArray[i].PlusItem.ItemName == Item.ItemName) { // 개수 증가 SlotArray[i].SetSlotCount(Count); return; } } } for (int i = 0; i < SlotArray.Length; i++) { // 해당 슬롯에 아이템이 없을 경우 if (SlotArray[i].PlusItem == null) { // 아이템 추가 SlotArray[i].AddItem(Item, Count); return; } } } #endregion // 함수
- AcquireItem() 호출은 플레이어가 아이템을 주웠을 경우에 호출 해주면 된다.
- 주석으로 코드의 역할을 표시해 이해하기 편하게 했습니다.
[인벤토리 슬롯 프리팹]
- InventorySlot 객체에 InventorySlot.cs를 넣어줍니다.
- ItemSlotCount_Img 객체는 아이템이 존재 할 경우에만 활성화 합니다.
[InventorySlot.cs]
#region 변수 [SerializeField] private Image ItemImg; // 아이템 이미지 [SerializeField] private GameObject ItemCountImg; [SerializeField] private TMP_Text ItemCountText; public ItemData PlusItem; // 획득한 아이템 public int ItemCount; // 획득한 아이템 수 #endregion // 변수 #region 프로퍼티 public InventorySlotToolTip ToolTip { get; set; } public Inventory Inven { get; set; } #endregion // 프로퍼티 #region 함수 /** 아이템 이미지 투명도 조절 */ private void SetColor(float Alpha) { Color color = ItemImg.color; color.a = Alpha; ItemImg.color = color; } /** 아이템 추가 */ public void AddItem(ItemData Item, int Count = 1) { this.PlusItem = Item; Inven.InventoryItemList.Add(PlusItem); ItemCount = Count; ItemImg.sprite = Item.ItemImg; // 아이템 타입에 따라 관리 if ItemCountImg.SetActive(true); ItemCountText.text = ItemCount.ToString(); // 투명도 SetColor(1); } /** 아이템 개수 조정 */ public void SetSlotCount(int Count) { // 개수 조정, 표시 ItemCount += Count; ItemCountText.text = ItemCount.ToString(); // 아이템이 없을경우 if(ItemCount <= 0) { // 슬롯 초기화 ClearSlot(); } } /** 슬롯을 교환한다 */ private void ChangeSlot() { // 데이터 덮어쓰기전 저장 ItemData ItemTemp = PlusItem; int ItemCountTemp = ItemCount; // 아이템 추가 AddItem(DragSlot.Instance.InventoryDragSlot.PlusItem, DragSlot.Instance.InventoryDragSlot.ItemCount); // 슬롯 교환 if (ItemTemp != null) { DragSlot.Instance.InventoryDragSlot.AddItem(ItemTemp, ItemCountTemp); } else { DragSlot.Instance.InventoryDragSlot.ClearSlot(); } } /** 슬롯 초기화 */ private void ClearSlot() { // 초기화 PlusItem = null; ItemCount = 0; ItemImg.sprite = null; // 투명도 SetColor(0); // 개수 표시 X ItemCountText.text = string.Empty; ItemCountImg.SetActive(false); } /** 클릭했을때 */ public void OnPointerClick(PointerEventData eventData) { // 오른쪽 클릭했을경우 if(eventData.button == PointerEventData.InputButton.Right) { // 아이템이 있을경우 if(PlusItem != null) { // 아이템 타입에 따라 장착 , 사용 여부 if PlusItem.Use(); Inven.InventoryItemList.Remove(PlusItem); ToolTip.HideToolTip(); // 무기 이미지, 탄약 상태창 갱신 UIManager.Instance.PlayerStatusTextUpdate(); UIManager.Instance.PlayerWeaponImgUpdate(); UIManager.Instance.PlayerAmmoTextUpdate(); Debug.Log(PlusItem.ItemName + "를 사용했습니다"); // 개수 조정 SetSlotCount(-1); } } } /** 드래그를 시작했을때 */ public void OnBeginDrag(PointerEventData eventData) { // 아이템이 있을경우 if (PlusItem != null) { // 드래그중인 아이템 세팅 DragSlot.Instance.InventoryDragSlot = this; DragSlot.Instance.DragSetImg(ItemImg); DragSlot.Instance.transform.position = eventData.position; } } /** 드래그 중일때 */ public void OnDrag(PointerEventData eventData) { // 아이템이 있을경우 if (PlusItem != null) { DragSlot.Instance.transform.position = eventData.position; } } /** 드래그가 끝났을때 */ public void OnEndDrag(PointerEventData eventData) { Debug.Log("EndDrag"); // 투명도, 비우기 DragSlot.Instance.SetColor(0); DragSlot.Instance.InventoryDragSlot = null; } /** 드랍했을때 */ public void OnDrop(PointerEventData eventData) { Debug.Log("Drop"); // 드래그중인 아이템이 있을경우 if (DragSlot.Instance.InventoryDragSlot != null) { // 아이템 교환 ChangeSlot(); } } /** 슬롯에 마우스를 올렸을 경우 */ public void OnPointerEnter(PointerEventData eventData) { if(PlusItem != null) { // 툴팁 보여주기 ToolTip.ShowToolTip(PlusItem); } } /** 슬롯에있는 마우스가 나갔을 경우 */ public void OnPointerExit(PointerEventData eventData) { if (PlusItem != null) { ToolTip.HideToolTip(); } } #endregion // 함수
- IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler, IPointerEnterHandler, IPointerExitHandler 인터페이스를 사용했습니다.
[DragSlot.cs]
#region 변수 [SerializeField] private Image ItemImg; public InventorySlot InventoryDragSlot; public static DragSlot Instance; #endregion // 변수 #region 함수 /** 초기화 */ private void Awake() { Instance = this; } /** 드래그중인 아이템 이미지 세팅 */ public void DragSetImg(Image ItemImg) { this.ItemImg.sprite = ItemImg.sprite; SetColor(1); } /** 아이템 이미지 투명도 조절 */ public void SetColor(float Alpha) { Color color = ItemImg.color; color.a = Alpha; ItemImg.color = color; } #endregion // 함수
[InventorySlotToolTip.cs]
#region 변수 [SerializeField] private GameObject ToolTip; [SerializeField] private TMP_Text ItemNameText; [SerializeField] private TMP_Text ItemDescText; [SerializeField] private TMP_Text ItemDescUseText; #endregion // 변수 #region 함수 /** 툴팁을 보여준다 */ public void ShowToolTip(ItemData Item) { ToolTip.SetActive(true); ItemNameText.text = Item.ItemName; ItemDescText.text = Item.ItemDesc; ItemDescUseText.text = Item.ItemDescUse; } /** 툴팁을 숨긴다 */ public void HideToolTip() { ToolTip.SetActive(false); } #endregion // 함수
[구현 완료]
- 인벤토리 시스템 구현하는 방법은 다양하게 존재합니다.
- 유니티에서 제공하는 인터페이스를 사용해 쉽게 구현했습니다.
- 유튜브에 구현하는 방법이 많이 존재하니 자신만의 코드로 응용하여 구현해 보는것을 추천합니다!
반응형'Unity' 카테고리의 다른 글
유니티 웅크리기 구현 - 플레이어 웅크리기 (0) 2024.02.03 유니티 움직임 구현 - 플레이어 이동 및 점프, 1인칭 시점 (0) 2024.01.25 유니티 데이터 저장/불러오기 - Json 데이터 저장/불러오기 (0) 2024.01.22 유니티 DOTween - 알림창 만들기 (0) 2024.01.18 유니티 카메라 확대,축소 / 마우스 드래그 - 카메라 이동 제한 (0) 2024.01.16