[Unity3D] 인벤토리 [Part 3] - Item Drag & Swap
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
1. 인벤토리 껍데기 만들기.
- 인벤토리의 Pivot 설정.
- 슬롯의 Pivot 설정.
- 슬롯 사이즈 설정.
- 슬롯 간 거리 설정.
- 슬롯의 가로, 세로 개수 설정.
- 인벤토리의 가로 사이즈, 세로 사이즈 설정.
- 슬롯 생성 및 부모설정.
- 모든 슬롯을 관리해줄 리스트를 생성.
2. 아이템 획득 시 검사조건 만들기 및 슬롯 기능 만들기.
- 아이템을 먹었을 때, 인벤토리 내의 슬롯을 모두 검사한다.
*검사조건 : -> 슬롯 내에 같은 아이템이 존재하는지?
-> 슬롯내에 같은 아이템이 존재할 경우 겹칠수 있는지?
-> 슬롯내에 같은 아이템이 존재하지만, 겹칠수 없는경우 빈 슬롯이 존재 하는지?
- 슬롯을 스택으로 만들어 아이템 관리하기
->아이템이 슬롯에 들어갔을때 이미지 변경.
->아이템을 겹칠경우 텍스트 갱신.
->아이템을 사용할 경우 텍스트 갱신.
->아이템을 모두 사용했을 때 이미지 변경.
3. 아이템 만들기 및 획득
- 아이템 타입 설정.
- 아이템의 이미지 설정.
- 아이템 겹칠수 있는 최대치 설정.
- 아이템과의 충돌로 아이템 획득하기.
4. 인벤토리내에 아이템 드래그 앤 드랍으로 아이템 옮기기 및 자리 바꾸기.
- 처음 마우스 버튼을 누를 때
- 누르고 이동할 때
- 드래그가 끝났을 때
- 누른 버튼을 땠을 때
의 4가지 상태로 나눠 드래그 앤 드랍 구현.
5. XML문서를 이용한 인벤토리 아이템 저장.
- Save
- Load
미리보기
4. 인벤토리내에 아이템 드래그 앤 드랍으로 아이템 옮기기 및 자리 바꾸기.
- 빈 이미지를 만든다.
이 이미지는 슬롯에 있는 아이템을 눌렀을 때 그 아이템의 이미지를 빈 이미지에 가져와 띄워주는 역할을 하는 이미지이다.
빈 이미지를 위와같이 Canvas의 자식으로 하나 만든다.
그리고, 태그를 하나 추가할 건데, 이 태그는 스크립트로 이 이미지를 가져오기 위함니다.
태그의 이름은 DragImg이다.
1 2 3 4 5 6 | public Transform Img; // 비어있는 이미지. void Start() { Img = GameObject.FindGameObjectWithTag("DragImg").transform; } | cs |
다음은 슬롯에 4가지 이벤트를 추가 해보자.
Event Trigger를 추가하면 된다.
드래그 앤 드롭은 4가지 형태로 볼 수 있다.
- 처음 눌렀을 때, (Pointer Down - Down)
- 누르고 드래그 할 때, (Drag - Drag)
- 드래그를 끝냈을 때, (End Drag - DragEnd)
- 마우스 버튼을 땠을 때. (Pointer Up - Up)
1). 처음 눌렀을 때.
- 슬롯에 아이템이 존재하지 않는다면 함수를 종료한다.
- 누른 버튼이 마우스 오른쪽 버튼이면 아이템을 사용한다.
- 빈 이미지 객체를 활성화 시킨다.
- 빈 이미지의 사이즈를 슬롯의 사이즈와 똑같이 변경한다.
=> 해상도가 달라졌을 때 슬롯의 크기가 바뀌므로 빈 객채의 이미지도 유동적으로 달라져야 한다.
- 빈 이미지의 sprite를 슬롯이 가지고 있는 아이템 이미지로 변경한다.
- 빈 이미지 객체의 위치를 마우스의 위치로 가져온다.
- 슬롯의 이미지를 없애준다.
- 슬롯의 텍스트 숫자를 없애준다.
2). 누르고 드래그 할 때.
- 슬롯에 아이템이 존재하지 않으면 함수를 종료한다.
- 빈 이미지의 위치를 마우스의 위치로 가져온다.
3). 드래그가 끝났을 때.
- 슬롯에 아이템이 존재하지 않으면 함수를 종료한다.
- 싱글톤을 이용해 인벤토리 내에 있는 Swap함수를 호출. 인자로 자신의 슬롯 스크립트와 빈 이미지의 현재 위치를 보낸다.
4). 마우스 버튼을 땠을 때.
- 슬롯에 아이템이 존재하지 않으면 함수를 종료한다.
- 빈 이미지 객체를 비활성화 시킨다.
- 현재 슬롯의 정보를 업데이트 시킨다.
마우스를 땠을 때 이벤트는 필요 없을것 같지만 필요하다.
빈 이미지 객체의 비활성화 및 슬롯의 이미지 업데이트에 필요하다.
빈 이미지 객체의 비활성화의 경우 드래그가 끝났을 때 수행해도 되지만,
아이템을 눌렀을 때 마우스를 움직이지 않으면 DragEnd함수는 호출되지 않는다.
그렇기 때문에 빈 이미지 객체의 활성화 조정을 이곳에서 할 필요가 있으며,
마찬가지로 없애주었던 이미지의 복구 또한 이곳에서 해 주어야 한다.
'ItemDrag' Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ItemDrag : MonoBehaviour { public Transform Img; // 빈 이미지 객체. private Image EmptyImg; // 빈 이미지. private Slot slot; // 현재 슬롯에 스크립트 void Start() { // 현재 슬롯의 스크립트를 가져온다. slot = GetComponent<Slot>(); // 빈 이미지 객체를 태그를 이용하여 가져온다. Img = GameObject.FindGameObjectWithTag("DragImg").transform; // 빈 이미지 객체가 가진 Image컴포넌트를 가져온다. EmptyImg = Img.GetComponent<Image>(); } public void Down() { // 슬롯에 아이템이 없으면 함수종료. if (!slot.isSlots()) return; // 아이템 사용시. if (Input.GetMouseButtonDown(1)) { slot.ItemUse(); return; } // 빈 이미지 객체를 활성화 시킨다. Img.gameObject.SetActive(true); // 빈 이미지의 사이즈를 변경한다.(해상도가 바뀔경우를 대비.) float Size = slot.transform.GetComponent<RectTransform>().sizeDelta.x; EmptyImg.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Size); EmptyImg.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, Size); // 빈 이미지의 스프라이트를 슬롯의 스프라이트로 변경한다. EmptyImg.sprite = slot.ItemReturn().DefaultImg; // 빈 이미지의 위치를 마우스위로 가져온다. Img.transform.position = Input.mousePosition; // 슬롯의 아이템 이미지를 없애준다. slot.UpdateInfo(true, slot.DefaultImg); // 슬롯의 텍스트 숫자를 없애준다. slot.text.text = ""; } public void Drag() { // isImg플래그가 false이면 슬롯에 아이템이 존재하지 않는 것이므로 함수 종료. if (!slot.isSlots()) return; Img.transform.position = Input.mousePosition; } public void DragEnd() { // isImg플래그가 false이면 슬롯에 아이템이 존재하지 않는 것이므로 함수 종료. if (!slot.isSlots()) return; // 싱글톤을 이용해서 인벤토리의 스왑함수를 호출(현재 슬롯, 빈 이미지의 현재 위치.) ObjManager.Call().IV.Swap(slot, Img.transform.position); //slot = null; } public void Up() { // isImg플래그가 false이면 슬롯에 아이템이 존재하지 않는 것이므로 함수 종료. if (!slot.isSlots()) return; // 빈 이미지 객체 비활성화. Img.gameObject.SetActive(false); // 슬롯의 아이템 이미지를 복구 시킨다. slot.UpdateInfo(true, slot.slot.Peek().DefaultImg); } } | cs |
드래그가 끝나는 함수, 그러니까 DragEnd함수의
Swap()함수를 살펴보도록 하자.
접근 방법은 싱글톤을 이용해서 Inventory스크립트에 접근해서 Swap함수를 호출한다.
이 함수의 인자는 2개를 받고 있는데, 현재 내가 누른 슬롯의 Slot 스크립트와 빈 이미지 객체의 위치이다.
'Inventory' 스크립트의 추가된 함수들을 살펴보자.
이곳 에서는 3가지 함수가 추가되었다.
public Slot NearDisSlot(Vector3 Pos) // 빈 이미지와 가까운 슬롯을 찾아 반환해주는 함수.
public void Swap(Slot slot, Vector3 Pos) // 슬롯 끼리의 내용물을 전체적으로 교환 해주는 함수.
void Swap(Slot xFirst, Slot oSecond) // Swap함수를 보조 해주는 함수. (두 개의 슬롯의 내용물을 교환한다.)
이번엔 UpdateInfo() 함수를 살펴보자.
이 함수는 슬롯에 추가된 함수로 아이템 존재유무와 이미지 업데이트의 역할을 맡고 있다.
Slot 스크립트에 아래의 함수를 추가해 주면 된다.
1 2 3 4 5 6 7 8 9 10 11 | // 슬롯에 대한 각종 정보 업데이트. public void UpdateInfo(bool isSlot, Sprite sprite) { this.isSlot = isSlot; transform.GetChild(0).GetComponent<Image>().sprite = sprite; if (slot.Count > 1) text.text = slot.Count.ToString(); else text.text = ""; } | cs |
또한 이러한 함수가 생겼으므로 Slot 스크립트의 AddItem() 함수에 대해서도
아래와 같이 고칠수 있게 된다.
1 2 3 4 5 6 | public void AddItem(Item item) { // 스택에 아이템 추가. slot.Push(item); UpdateInfo(true, item.DefaultImg); } | cs |
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] 인벤토리 [Part 4] - Load (3) | 2017.04.24 |
---|---|
[Unity3D] 인벤토리 [Part 4] - Save (3) | 2017.04.23 |
[Unity3D] 인벤토리 [Part 2] - Item Add (13) | 2017.04.12 |
[Unity3D] 인벤토리 [Part 1] - Inventory UI (5) | 2017.04.07 |
[Unity3D] 인벤토리 [Part 0] (0) | 2017.04.06 |