[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 |
[Unity3D] 인벤토리 [Part 2] - Item Add
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
1. 인벤토리 껍데기 만들기.
- 인벤토리의 Pivot 설정.
- 슬롯의 Pivot 설정.
- 슬롯 사이즈 설정.
- 슬롯 간 거리 설정.
- 슬롯의 가로, 세로 개수 설정.
- 인벤토리의 가로 사이즈, 세로 사이즈 설정.
- 슬롯 생성 및 부모설정.
- 모든 슬롯을 관리해줄 리스트를 생성.
2. 아이템 획득 시 검사조건 만들기 및 슬롯 기능 만들기.
- 아이템을 먹었을 때, 인벤토리 내의 슬롯을 모두 검사한다.
*검사조건 : -> 슬롯 내에 같은 아이템이 존재하는지?
-> 슬롯내에 같은 아이템이 존재할 경우 겹칠수 있는지?
-> 슬롯내에 같은 아이템이 존재하지만, 겹칠수 없는경우 빈 슬롯이 존재 하는지?
- 슬롯을 스택으로 만들어 아이템 관리하기
->아이템이 슬롯에 들어갔을때 이미지 변경.
->아이템을 겹칠경우 텍스트 갱신.
->아이템을 사용할 경우 텍스트 갱신.
->아이템을 모두 사용했을 때 이미지 변경.
3. 아이템 만들기 및 획득
- 아이템 타입 설정.
- 아이템의 이미지 설정.
- 아이템 겹칠수 있는 최대치 설정.
- 아이템과의 충돌로 아이템 획득하기.
4. 인벤토리내에 아이템 드래그 앤 드랍으로 아이템 옮기기 및 자리 바꾸기.
- 처음 마우스 버튼을 누를 때
- 누르고 이동할 때
- 드래그가 끝났을 때
- 누른 버튼을 땠을 때
의 4가지 상태로 나눠 드래그 앤 드랍 구현.
5. XML문서를 이용한 인벤토리 아이템 저장.
- Save
- Load
미리보기
2. 아이템 획득 시 검사조건 만들기 및 슬롯 기능 만들기.
를 진행하기 전에 3번부터 합시다.
3. 아이템 만들기 및 획득.
만약 아이템이 플레이어와 충돌한다면
아이템은 플레이어 인벤토리 스크립트에 존재하는 AddItem()함수를 호출한다.
※ 아이템쪽에서 플레이어와의 충돌을 감지한다.
※ 왜 하필 인벤토리 스크립트에서 AddItem()을 호출하는가?
슬롯에 직접 아이템을 넣으면 안되는가?
아이템을 먹었다고 해서 인벤토리에 아이템이 무조건 들어가는것이 아니다.
인벤토리가 꽉 차 있는경우 아이템 획득에 실패할수 있다.
또한 인벤토리가 꽉 차 있지만 인벤토리 내에 똑같은 아이템이 존재하여
먹을수 있는 경우도 있다.
이러한 경우에 수를 다 시도해 보기 위해 모든 슬롯을 관리하는 인벤토리 스크립트에
AddItem()을 호출해줄 필요가 있다.
'Item' 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 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class Item : MonoBehaviour { public enum TYPE { HP, MP } public TYPE type; // 아이템의 타입. public Sprite DefaultImg; // 기본 이미지. public int MaxCount; // 겹칠수 있는 최대 숫자. void AddItem() { // 싱글톤을 이용해서 인벤토리 스크립트를 가져온다. Inventory iv = ObjManager.Call().IV; // 아이템 획득에 실패할 경우. if (!iv.AddItem(this)) Debug.Log("아이템이 가득 찼습니다."); else // 아이템 획득에 성공할 경우. gameObject.SetActive(false); // 아이템을 비활성화 시켜준다. } // 충돌체크 void OnTriggerEnter(Collider _col) { // 플레이어와 충돌하면. if (_col.gameObject.layer == 10) AddItem(); } } | cs |
싱글톤이 없을 경우. 'Item' Script
아이템을 먹었을 때 엉뚱한 아이템이 인벤토리에 들어가면 안된다.
그렇기 때문에 아이템 자체에 아이템의 타입(종류)과 그 아이템에 해당하는 이미지 정보,
그리고 아이템을 몇개까지 겹칠수 있는지? 에 대한 정보를 가지고 있을 필요가 있다.
아이템에 대한 인스펙터창 정보이다.
플레이어에 대한 레이어 설정도 잊지 말도록 하자.
2. 아이템 획득 시 검사조건 만들기 및 슬롯 기능 만들기.
아이템이 인벤토리 스크립트에 존재하는 AddItem() 함수를 호출했다.
AddItem()안에서 해야 될것은 두 가지가 있다.
첫 번째는 넣을려는 아이템과 똑같은 아이템이 슬롯에 존재하는가?
존재 한다면 겹칠수 있는 최대치는 넘지 않았는가?
위의 조건에 해당되면 아이템을 슬롯에 넣는다.
두 번째는 위에 조건을 검사했지만 해당되지 않을 때 하는 검사이다.
똑같은 아이템이 없기 때문에 그냥 비어있는 슬롯에 아이템을 넣어주면 된다.
위의 모든 조건에 해당되지 않는다면 아이템을 먹지 못하기 때문에 AddItem()함수는 false를 반환하면 된다.
슬롯에 존재하는 아이템과 넣을려는 아이템이 똑같은지를 검사하기 위해서는
슬롯에 존재하는 아이템의 정보를 끌어올 필요가 있다.
그러기 위해서는 위에 조건의 작성보다 선행되어야 하는 것이 있는데
바로 슬롯 스크립트의 작성이다.
'slot' 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 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Slot : MonoBehaviour { public Stack<Item> slot; // 슬롯을 스택으로 만든다. public Text text; // 아이템에 개수를 표현해줄 텍스트. public Sprite DefaultImg; // 슬롯에 있는 아이템을 다 사용할 경우 아무것도 없는 이미지를 넣어줄 필요가 있다. private Image ItemImg; private bool isSlot; // 현재 슬롯이 비어있는지? public Item ItemReturn() { return slot.Peek(); } // 슬롯에 존재하는 아이템이 뭔지 반환. public bool ItemMax(Item item) { return ItemReturn().MaxCount > slot.Count; } // 겹칠수 있는 한계치를 넘으면. public bool isSlots() { return isSlot; } // 슬롯이 현재 비어있는지? 에 대한 플래그 반환. public void SetSlots(bool isSlot) { this.isSlot = isSlot; } void Start() { // 스택 메모리 할당. slot = new Stack<Item>(); // 맨 처음엔 슬롯이 비어있다. isSlot = false; // 인벤토리 및 슬롯의 크기가 커지가나 작아지면 // 텍스트 폰트의 크기도 유동적으로 바뀌어야 한다. // 텍스트 폰트의 크기를 슬롯에 크기에 따라 변경해주는 구문이다. //RectTransform rect = text.gameObject.GetComponent<RectTransform>(); float Size = text.gameObject.transform.parent.GetComponent<RectTransform>().sizeDelta.x; text.fontSize = (int)(Size * 0.5f); // 텍스트 컴포넌트의 RectTransform을 가져온다. // 텍스트 객체의 부모 객체의 x지름을 가져온다. // 폰트의 크기를 부모 객체의 x지름 / 2 만큼으로 지정해준다. ItemImg = transform.GetChild(0).GetComponent<Image>(); } public void AddItem(Item item) { // 스택에 아이템 추가. slot.Push(item); UpdateInfo(true, item.DefaultImg); } // 아이템 사용. public void ItemUse() { // 슬롯이 비어있으면 함수를 종료. if (!isSlot) return; // 슬롯에 아이템이 1개인 경우. // 아이템이 1개일 때 사용하게 되면 0개가 된다. if (slot.Count == 1) { // 혹시 모를 오류를 방지하기 위해 slot리스트를 Clear해준다 slot.Clear(); // 아이템 사용으로 인해 아이템 개수를 표현하는 텍스트가 달라졌으므로 업데이트 시켜준다. UpdateInfo(false, DefaultImg); return; } slot.Pop(); UpdateInfo(isSlot, ItemImg.sprite); } // 슬롯에 대한 각종 정보 업데이트. public void UpdateInfo(bool isSlot, Sprite sprite) { SetSlots(isSlot); // 슬롯이 비어있다면 false 아니면 true 셋팅. ItemImg.sprite = sprite; // 슬롯안에 들어있는 아이템의 이미지를 셋팅. text.text = slot.Count > 1 ? slot.Count.ToString() : ""; // 아이템이 2개 이상일때면 텍스트로 표현. ItemIO.SaveDate(); // 인벤토리에 변동사항이 생겼으므로 저장. } } | cs |
텍스트 정보.
슬롯 스크립트의 작성이 끝났으면 인벤토리의 AddItem()함수를 작성할 수 있게 된다.
'Inventory' 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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class Inventory : MonoBehaviour { // 공개 public List<GameObject> AllSlot; // 모든 슬롯을 관리해줄 리스트. public RectTransform InvenRect; // 인벤토리의 Rect public GameObject OriginSlot; // 오리지널 슬롯. public float slotSize; // 슬롯의 사이즈. public float slotGap; // 슬롯간 간격. public float slotCountX; // 슬롯의 가로 개수. public float slotCountY; // 슬롯의 세로 개수. // 비공개. private float InvenWidth; // 인벤토리 가로길이. private float InvenHeight; // 인밴토리 세로길이. private float EmptySlot; // 빈 슬롯의 개수. void Awake() { // 인벤토리 이미지의 가로, 세로 사이즈 셋팅. InvenWidth = (slotCountX * slotSize) + (slotCountX * slotGap) + slotGap; InvenHeight = (slotCountY * slotSize) + (slotCountY * slotGap) + slotGap; // 셋팅된 사이즈로 크기를 설정. InvenRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, InvenWidth); // 가로. InvenRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, InvenHeight); // 세로. // 슬롯 생성하기. for (int y = 0; y < slotCountY; y++) { for (int x = 0; x < slotCountX; x++) { // 슬롯을 복사한다. GameObject slot = Instantiate(OriginSlot) as GameObject; // 슬롯의 RectTransform을 가져온다. RectTransform slotRect = slot.GetComponent<RectTransform>(); // 슬롯의 자식인 투명이미지의 RectTransform을 가져온다. RectTransform item = slot.transform.GetChild(0).GetComponent<RectTransform>(); slot.name = "slot_" + y + "_" + x; // 슬롯 이름 설정. slot.transform.parent = transform; // 슬롯의 부모를 설정. (Inventory객체가 부모임.) // 슬롯이 생성될 위치 설정하기. slotRect.localPosition = new Vector3((slotSize * x) + (slotGap * (x + 1)), -((slotSize * y) + (slotGap * (y + 1))), 0); // 슬롯의 자식인 투명이미지의 사이즈 설정하기. slotRect.localScale = Vector3.one; slotRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, slotSize); // 가로 slotRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, slotSize); // 세로. // 슬롯의 사이즈 설정하기. item.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, slotSize - slotSize * 0.3f); // 가로. item.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, slotSize - slotSize * 0.3f); // 세로. // 리스트에 슬롯을 추가. AllSlot.Add(slot); } } // 빈 슬롯 = 슬롯의 숫자. EmptySlot = AllSlot.Count; } // 아이템을 넣기위해 모든 슬롯을 검사. public bool AddItem(Item item) { // 슬롯에 총 개수. int slotCount = AllSlot.Count; // 넣기위한 아이템이 슬롯에 존재하는지 검사. for (int i = 0; i < slotCount; i++) { // 그 슬롯의 스크립트를 가져온다. Slot slot = AllSlot[i].GetComponent<Slot>(); // 슬롯이 비어있으면 통과. if (!slot.isSlots()) continue; // 슬롯에 존재하는 아이템의 타입과 넣을려는 아이템의 타입이 같고. // 슬롯에 존재하는 아이템의 겹칠수 있는 최대치가 넘지않았을 때. (true일 때) if (slot.ItemReturn().type == item.type && slot.ItemMax(item)) { // 슬롯에 아이템을 넣는다. slot.AddItem(item); return true; } } // 빈 슬롯에 아이템을 넣기위한 검사. for (int i = 0; i < slotCount; i++) { Slot slot = AllSlot[i].GetComponent<Slot>(); // 슬롯이 비어있지 않으면 통과 if (slot.isSlots()) continue; slot.AddItem(item); return true; } // 위에 조건에 해당되는 것이 없을 때 아이템을 먹지 못함. return false; } } | cs |
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] 인벤토리 [Part 4] - Save (3) | 2017.04.23 |
---|---|
[Unity3D] 인벤토리 [Part 3] - Item Drag & Swap (5) | 2017.04.13 |
[Unity3D] 인벤토리 [Part 1] - Inventory UI (5) | 2017.04.07 |
[Unity3D] 인벤토리 [Part 0] (0) | 2017.04.06 |
[Unity3D] 객체 미리 생성 후 재활용 - Memory pool [Part 5] 추가사항 (2) | 2017.04.05 |
단방향 연결리스트 반대로 뒤집기.
1->2->3->null 이렇게 연결되어있는 리스트가 있다고 하자. (이 때 Head : 1)
이 리스트의 내용을 반대로 뒤집을 것이다.
뒤집으면 3->2->1->null이 된다. (이 때 Head : 3)
※ 양방향으로 연결되어있지 않다.
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 | void Revers() { if(pHead == NULL) { printf("데이터가 존재하지 않습니다. \n"); return; } int Count = DataLen - 1; Node* pNode = pHead; Node* pPrev; Node* pTemp; while(pNode->pNext != NULL) pNode = pNode->pNext; pTemp = pNode; while( Count > 0 ) { pNode = pHead; for(int i = 0; i < Count; i++) { pPrev = pNode; pNode = pNode->pNext; } pNode->pNext = pPrev; Count--; } pPrev->pNext = NULL; pHead = pTemp; } | cs |
방법은 생각해보면 간단하다.
현재 노드가 가리키는 포인터를 반대 방향의 노드를 향하게 하면 되는 일이다.
Head에 접근하여 순서대로 끝 노드까지 접근하자.
현재 끝 노드는 null를 가르키고 있다.
이 노드의 포인터를 반대 방향의 노드에 가르켜야 한다.
여기서 문제가 생긴다.
1. 각 노드의 포인터 방향을 모두 바꾼다고 했을 때 1은 null을 가르켜야 한다.
하지만 1은 Head이다. 방향이 바뀐다면 3이 Head가 될 필요가 있다.
그러면 포인터의 방향을 바꿔주는 작업을 하기전에 끝 노드에 접근하여 그 노드를 가르킬 노드를 임시로 생성해줄 필요가 있다.
그 부분이 15,16행이다.
15,16행은 끝 노드로 접근하는 과정이고 while이 끝나게 되면 pNode는
끝 노드를 가르킨채 반복문에서 빠져나오게 된다.
이때 18행에서 임시로 변수를 생성해주고 그 변수가 끝 노드를 가르키도록 하면 된다.
※ Head를 처음부터 바꾸지 않는다.
각각의 노드들의 포인터를 바꿔줘야 하는데,
한 번에 모든 노드들의 방향을 바꿀수 없기 때문이다.
노드 하나의 포인터를 바꿔주면 다시 처음부터 노드에 접근하여 포인터 방향이 바뀌지 않은 노드까지
이동 후 포인터 방향을 바꿔준다. 모든 포인터 방향이 바뀔때까지 이 작업을 반복한다.
모든 포인터의 방향이 바뀌었을 때 Head에 임시 변수를 대입하면 모든 작업은 끝나게 된다.
pNode를 3까지 접근시켜 3의 포인터를 null이 아니라 2를 가르키게 하자.
그러면 2와 3은 서로를 가르키게 된다.
그러면 다시 pNode를 2까지 접근 시키고 2의 포인터를 1을 가르키게 하자.
pNode를 1에 접근시켜 1의 포인터를 null을 가르키게 하자.
이제 Head를 3으로 옮기자 3의 위치는 임시변수인 Temp가 가지고 있다.
※ DataLen은 전역변수로 리스트에 데이터가 하나 추가될때마다 1씩 증가한다.
즉, 리스트에 데이터가 3개 존재한다면 DataLen은 3이된다.
'자료구조' 카테고리의 다른 글
덱(Deque) (0) | 2017.05.31 |
---|---|
해시 테이블 (Hash Table) (0) | 2017.01.08 |
큐(Queue) (0) | 2017.01.07 |
스택(Stack) (0) | 2017.01.07 |
단방향 연결 리스트(Linked List) (0) | 2017.01.06 |