Unity Personal MiniGame(3)

장현태입니다·2025년 6월 4일

Unity Personal Project

#개인적인 학습내용을 바탕으로 작성한 내용이므로 틀린 내용이 있을 수 있습니다.

ObjectPool을 이용한 인벤토리 구성
ObjectPool - PooledObject
SlotParent(ObjectPool List 사용) - Slot(PooledObject 자식)
이런 형식으로 외부 아이템 인벤토리, 나의 인벤토리를 구성할 것이다.

먼저 Singleton 패턴을 사용한 인벤토리부터 살펴보자

InventoryManager)

추가 GameObject가 생성 되었으며, canMove의 경우 플레이어가 인벤토리 창을 열었을경우 추가 움직임 제한을 걸어주기 위해 만들었다.
sum의 경우 최대 무게를 제한하기 위해 만들었지만 무게가 올라가는것은 구현 하였지만 최대 무게가 됐을 때 움직임 제어나 제한을 걸어주지는 않았다.

AddItem : 내 인벤토리의 리스트 갯수가 12보다 작을 경우에만 넣을 수 있도록 설정해주었다.
RemoveItem : 이부분에서 많이 헷갈렸는데 이전까진 item을 사용할 때 아이템에 대한 정보로만 구현하였는데, 여기서 인덱스와 item의 id를 추가적으로 더해서 해당 인덱스를 찾아 제거해주는 index를 가져와서 list에서 제거작업을 진행 해주었다 나중에 MySlotParent(내 인벤토리 슬롯 관리)에서 더 알아보자

간단한 외부 아이템을 sideItemList에 더하고 뺴는 작업

플레이어가 사용해서 inventoryCanvas가 활성화인지 비활성인지 판단하고 SetActive작업을 해줄 함수와, 아이템 값에 따라 변하는 값을 넘길 함수

ObjectPool)

풀을 생성자로 만들어서 여러곳에 생성 할 수 있게 해주었다 (외부 인벤토리, 내 인벤토리에 사용)

GetPool : 풀을 가져다 쓸 경우 사용할 함수로 풀을 사용할 때 만약 PoolList안에 갯수가 하나 이상일경우 오브젝트의 끝에서 부터 꺼내서 사용하는 방법을 사용했다 이 때, 오브젝트가 비워있거나 파괴된 오브젝트일 경우 이미 사용하고 없어진 형태라 넘어가는 식으로 구성하였다.
-> MissingReferenceException : 이미 파괴된 오브젝트에 접근하려고 하는 에러

AddPool : 또한 비워있거나 파괴된 오브젝트일경우 return하고 그외의 경우에 위에 정의한 Parent에 저장하기 위해 사용. 사용한 오브젝트풀을 반환 할 때 사용할 함수

CreatePool : 풀오브젝트를 생성할 떄 사용

PooledObject)

오브젝트 풀을 반환하고 자신을 정의 하기위한 클래스

SlotParent) 외부 아이템

오브젝트 풀에서 가져온 sideSlotPool, slotList는 아이템의 인덱스를 정해주기 위해 선언,

외부 아이템을 넣기 위해 사용 된 클래스로 item의 정보를 가져오면 풀에서 가져와서 하나의 오브젝트를 사용하는데 이 때 sideSlot에 정보를 저장하고 이 정보를 list에 저장한다. 이 sideSlot은 while문을 통해 해당 아이템의 id가 인덱스에 존재하는지 확인한 후 해당 인덱스가 없을때까지 index를 더해준다 이 인덱스를 item.ID에 할당한 후 아이템의 init()을 사용해서 아이템의 정보, 부모정보, 인덱스정보를 리스트에 저장한다.

RemoveSideItem : 빈 targetSlot을 생성해주고 if문을 통해 list의 해당 인덱스가 null이 아니고, 리스트에 파라미터로 받아온 아이템이 맞을경우 targetSlot에 해당 인덱스의 리스트아이템을 저장하고 break해준다.
그리고 그 targetSlot이 리스트에 할당이 되어 null이 아닐경우 PooledObject의 ReturnObjectPool()을 실행해주고 InventorySlot(외부 슬롯)의 Outit(Init에 넣었던 값을 null로 바꿔주는 작업)을 실행 해주며, slotList에서 해당 아이템을 삭제해준다.

InventorySlot) 외부 아이템

선언할 때 아이템의 정보를 저장할 Init(), 삭제할 때 정보를 뺄 Outit()

SetSlot의 경우 가져온 아이템의 정보를 UI에 보여 줄 형태

OnBeginDrag : 현재 위치를 저장
OnDrag : 마우스 왼쪽 버틀을 사용해서 드래그 하고있을 때 InventroyManager에서 게임 오브젝트 inventoryPanel을 true로 설정, 그리고 드래그하는 위치에 eventData.delta를 더해주고 드래그 위치를 저장해준다.

OnEndDrag : 드래그 마친 지점이 저장한 dragPos를 가져와서 if문에 대조하고 만약 itemData가 없을경우도 else문으로 가도록 설정하였다.
DropItem클래스에서 아이템을 드래그 하는데 모든 DropItem의 정보를 저장하고 저장한 DropItem을 foreach문을 통해 드래그 했을 경우 해당 아이템과 DropItem 클래스의 아이템과 동일하다면 이벤트를 발생 하도록 설정하였다 (DropItem.draggedItem = itemData; - 의미없음)

AddDrag : InventoryManager의 MySlotParent를 가져와서 해당 클래스의 함수를 실행 하고 InventroyManager에 접근하여 MySlotParent의 리스트에 아이템을 지우며, InventoryManager에서 아이템을 지운다.

MySlotParent) 내 인벤토리

SlotParent와 구성이 비슷하다. 다른 점이라면
AddItem : InventoryManager에 직접 아이템 데이터를 전달
RemoveItem : 이전에 말했던 아이템 정보(targetSlot.itemData.ID)를 인덱스 값도 같이 전달하게된다.

MyInventorySlot)

여기까진 InventorySlot과 비슷하다

마우스 오른쪽키를 누를경우 Player의 정보를 받아와서 아이템에 해당하는 함수를 실행하도록 설정 하였다.

아이템을 주워서 내 인벤토리에 넣었다면 삭제 해주는 Destroy를 사용 했는데 이 때 해당 아이템이 아닌 하이라키의 맨 밑의 아이템이 사라지는 버그가 있었다 해결하기 위해 static을 활용해서 아이템에 접근 할려고 했지만 제대로 되지 않았다.

이전에 드래그 했을 때 아이템을 삭제하는데 드래그가 내 인벤토리 칸에 이뤄지지 않았는데 삭제되면 안되기 때문에 범위를 설정 해주었었다. 그리고 그 드래그가 해당 아이템이 맞을경우 삭제하도록 이벤트를 설정 하였고, 아이템 삭제를 진행할 때 해당 아이템이 바로 없어지게되면 넣어질 경우 버그가 생기기 때문에 다음 프레임에 실행 하도록 설정 하였다.

layer가 7일경우(Player) trigger를 실행 시켜서 SlotParen와 InventoryManager에 접근 하였다.

triggerExit의 경우이고, DropWeapon은 사용했다가 어디서 사용했는지 까먹었다.


변경해야할점

1) S.O로 생성한 ID의경우 InventorySlot 자체에서 가져야하지 스크립터블에서 가지면 안됨.
2) 아이템 자체를 넘기는게 아니라 인덱스로 넘겨야함

0개의 댓글