신입 받아주는 회사 없나
취직하고 싶다.
'잡담' 카테고리의 다른 글
잡담 (0) | 2017.05.05 |
---|---|
컴활 1급 실기 합격. (0) | 2017.05.05 |
[Unity3D] 인벤토리 [Part 4] - Load
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
1. 인벤토리 껍데기 만들기.
- 인벤토리의 Pivot 설정.
- 슬롯의 Pivot 설정.
- 슬롯 사이즈 설정.
- 슬롯 간 거리 설정.
- 슬롯의 가로, 세로 개수 설정.
- 인벤토리의 가로 사이즈, 세로 사이즈 설정.
- 슬롯 생성 및 부모설정.
- 모든 슬롯을 관리해줄 리스트를 생성.
2. 아이템 획득 시 검사조건 만들기 및 슬롯 기능 만들기.
- 아이템을 먹었을 때, 인벤토리 내의 슬롯을 모두 검사한다.
*검사조건 : -> 슬롯 내에 같은 아이템이 존재하는지?
-> 슬롯내에 같은 아이템이 존재할 경우 겹칠수 있는지?
-> 슬롯내에 같은 아이템이 존재하지만, 겹칠수 없는경우 빈 슬롯이 존재 하는지?
- 슬롯을 스택으로 만들어 아이템 관리하기
->아이템이 슬롯에 들어갔을때 이미지 변경.
->아이템을 겹칠경우 텍스트 갱신.
->아이템을 사용할 경우 텍스트 갱신.
->아이템을 모두 사용했을 때 이미지 변경.
3. 아이템 만들기 및 획득
- 아이템 타입 설정.
- 아이템의 이미지 설정.
- 아이템 겹칠수 있는 최대치 설정.
- 아이템과의 충돌로 아이템 획득하기.
4. 인벤토리내에 아이템 드래그 앤 드랍으로 아이템 옮기기 및 자리 바꾸기.
- 처음 마우스 버튼을 누를 때
- 누르고 이동할 때
- 드래그가 끝났을 때
- 누른 버튼을 땠을 때
의 4가지 상태로 나눠 드래그 앤 드랍 구현.
5. XML문서를 이용한 인벤토리 아이템 저장.
- Save
- Load
5. XML문서를 이용한 인벤토리 아이템 저장. - Load
우선 흐름부터 살펴보도록 하자.
1. InventoryData.xml이라는 파일이 존재하는지 확인한다.
=> 파일이 존재하지 않으면 함수종료.
=>System.IO.File.Exists(경로) : 이 함수는 경로내의 파일이 존재하면 true 존재하지 않으면 false를 되돌려주는 함수이다.
2. xml문서를 하나 만든다.
3. 만든 xml문서에 InventoryData.xml을 불러온다.
4. 요소를 하나 만들어서 불러온 xml파일로 초기화 시킨다.
5. 필드를 하나 만들어서 InventoryData.xml문서의 최상위에 있는 필드로 초기화 시킨다.
6. 필드의 존재하는 슬롯번호를 하나 꺼내와서 슬롯의 n번째 번호를 가져와, 그 번호를 이용하여 슬롯의 'Slot'스크립트를 꺼내온다.
7. 아이템 클래스로 아이템 객체를 하나 만든다.
8. 필드에서 Name, MaxCount를 꺼내와서 새로 생성된 아이템의 내용을 초기화 시킨다.
Item Script 추가사항.
9. 필드에서 Count를 꺼내와서 Count의 수만큼 반복문을 돌린다.
=> 위에서 6에서 가져왔던 Slot스크립트를 이용하여 이 슬롯에 아이템을 AddItem()을 호출하여 집어넣는다.
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 | public static List<GameObject> Load(List<GameObject> SlotList) { if (!System.IO.File.Exists(Application.dataPath + "/Save/InventoryData.xml")) return SlotList; XmlDocument XmlDoc = new XmlDocument(); // 문서를 만듬. XmlDoc.Load(Application.dataPath + "/Save/InventoryData.xml"); // 경로상의 XML파일을 로드 XmlElement Xmlel = XmlDoc["ItemDB"]; // 속성 ItemDB에 접속. foreach (XmlElement ItemElement in Xmlel.ChildNodes) { // 슬롯의 n번째 스크립트를 가져온다. Slot slot = SlotList[System.Convert.ToInt32(ItemElement.GetAttribute("SlotNumber"))].GetComponent<Slot>(); // 아이템 생성. Item item = new Item(); // 아이템의 정보를 셋팅한다. string Name = ItemElement.GetAttribute("Name"); // 아이템 이름을 가져옴. int MaxCount = System.Convert.ToInt32(ItemElement.GetAttribute("MaxCount")); // 겹칠수 있는 한계. item.Init(Name, MaxCount); // 위의 가져온 정보를 토대로 아이템의 정보를 초기화. int Count = System.Convert.ToInt32(ItemElement.GetAttribute("Count")); // 슬롯에 아이템을 n개 집어넣기 위해서 개수를 가져옴. for (int i = 0; i < Count; i++) slot.AddItem(item); } return SlotList; } | cs |
'Inventory' 스크립트에 Awake()에서는 인벤토리와 슬롯이 만들어진다.
슬롯이 만들어지게 되면 슬롯객체 안에 존재하는 'Slot' 스크립트의 Start()가 수행되는데,
이 Start()의 수행이 끝난뒤 우리가 저장한 정보를 Load해야한다.
만약 Inventory 스크립트의 Awake()가 수행되기전에 Load()를 수행하면 아직 만들어지지도 않은 슬롯에
정보를 할당하려 했으므로 에러를 내뿜게 된다.
마찬가지로 Slot 스크립트의 Start()가 수행되기전에 Load()를 수행한다면 슬롯의 아이템을 담아놓는 Stack자체가
생성되지 않았기 때문에 에러를 내뿜게 된다.
그렇기 때문에 모든 슬롯의 Start()가 끝나게 되면 Load를 수행하면 된다.
하지만 모든 슬롯의 Start()의 수행이 언제 끝날지는 알 수 없으므로 사용자가 임의로 시작을 지연시키고 그 뒤 정보를 Load시킨다. 불안정한 방법이지만 Awake() 및 Start() 수행속도는 빠른 편이므로 시간을 아주 조금만 지연시켜주면 된다.
Inventory스크립트에 Awake()안에 Invoke를 이용하여 Init()함수를 호출해주고, 시간을 0.01f초 지연시키도록 하자.
1 2 3 4 5 6 | Invoke("Init", 0.01f); void Init() { ItemIO.Load(AllSlot); } | cs |
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] 헥사게임 만들기 두 번째 - 블럭보드 만들기. (0) | 2018.02.13 |
---|---|
[Unity3D] 헥사게임 만들기 첫 번째 - 리소스 준비하기 및 캔버스 크기 설정. (0) | 2018.02.11 |
[Unity3D] 인벤토리 [Part 4] - Save (3) | 2017.04.23 |
[Unity3D] 인벤토리 [Part 3] - Item Drag & Swap (5) | 2017.04.13 |
[Unity3D] 인벤토리 [Part 2] - Item Add (13) | 2017.04.12 |
[Unity3D] 인벤토리 [Part 4] - Save
※ 주의
이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.
Menu
1. 인벤토리 껍데기 만들기.
- 인벤토리의 Pivot 설정.
- 슬롯의 Pivot 설정.
- 슬롯 사이즈 설정.
- 슬롯 간 거리 설정.
- 슬롯의 가로, 세로 개수 설정.
- 인벤토리의 가로 사이즈, 세로 사이즈 설정.
- 슬롯 생성 및 부모설정.
- 모든 슬롯을 관리해줄 리스트를 생성.
2. 아이템 획득 시 검사조건 만들기 및 슬롯 기능 만들기.
- 아이템을 먹었을 때, 인벤토리 내의 슬롯을 모두 검사한다.
*검사조건 : -> 슬롯 내에 같은 아이템이 존재하는지?
-> 슬롯내에 같은 아이템이 존재할 경우 겹칠수 있는지?
-> 슬롯내에 같은 아이템이 존재하지만, 겹칠수 없는경우 빈 슬롯이 존재 하는지?
- 슬롯을 스택으로 만들어 아이템 관리하기
->아이템이 슬롯에 들어갔을때 이미지 변경.
->아이템을 겹칠경우 텍스트 갱신.
->아이템을 사용할 경우 텍스트 갱신.
->아이템을 모두 사용했을 때 이미지 변경.
3. 아이템 만들기 및 획득
- 아이템 타입 설정.
- 아이템의 이미지 설정.
- 아이템 겹칠수 있는 최대치 설정.
- 아이템과의 충돌로 아이템 획득하기.
4. 인벤토리내에 아이템 드래그 앤 드랍으로 아이템 옮기기 및 자리 바꾸기.
- 처음 마우스 버튼을 누를 때
- 누르고 이동할 때
- 드래그가 끝났을 때
- 누른 버튼을 땠을 때
의 4가지 상태로 나눠 드래그 앤 드랍 구현.
5. XML문서를 이용한 인벤토리 아이템 저장.
- Save
- Load
미리보기
5. XML문서를 이용한 인벤토리 아이템 저장. - Save
인벤토리에 들어있는 아이템의 정보를 XML문서에 Save하여,
게임 시작 시 XML문서를 토대로 정보를 Load하려고 한다.
시작하기 전에 Save및 Load의 호출를 어디에서 할 것인가 부터 살펴보자.
Save는 인벤토리 내에 아이템에 대한 정보변환이 일어났을 때 수행해야한다.
그렇다면 정보변환는 언제 일어나는 것일까?
- 아이템을 먹었을 때
- 아이템을 드래그하여 다른 슬롯으로 옮겼을 때.
- 아이템 끼리 Swap했을 때.
이 모든 변화가 일어났을 때 Save는 호출되어야 한다.
우리가 만든 함수 중 위의 변화가 일어났을 때
어김없이 호출되는 함수가 하나 있다.
'Slot' 스크립트에 존재하는 UpdateInfo() 함수이다.
이 함수는 위의 모든 상황에서 호출되는 함수다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | // 슬롯에 대한 각종 정보 업데이트. 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 = ""; ItemIO.SaveDate(); } | cs |
※ 이렇게 맨 밑에다 Save를 호출하면 된다.
그렇다면 Load는 언제 호출되어야 할까?
인벤토리가 만들어지기 전에 Load가 호출되면 안된다.
인벤토리가 생성되고.
슬롯이 생성되고(Inventory 스크립트의 Awake()함수의 호출).
슬롯객체에 붙어있는 Slot 스크립트의 Start()가 호출이 끝난 뒤.
Load가 호출되어야 한다.
Save함수를 호출할 때 아이템에대한 정보가 XML문서로 만들어지게 된다.
이 스크립트를 이해하기 위해서는 우리는 XML문서가 어떻게 구성되어 있는지 파악할 필요가 있다.
정보가 저장된 XML문서의 구성은 이렇다.
1 2 3 4 5 6 7 8 9 10 11 | <ItemDB> <Item SlotNumber="1" Name="MP" Count="3" MaxCount="3" /> <Item SlotNumber="2" Name="MP" Count="3" MaxCount="3" /> <Item SlotNumber="4" Name="HP" Count="3" MaxCount="3" /> <Item SlotNumber="5" Name="MP" Count="3" MaxCount="3" /> <Item SlotNumber="6" Name="MP" Count="3" MaxCount="3" /> <Item SlotNumber="8" Name="HP" Count="3" MaxCount="3" /> <Item SlotNumber="9" Name="HP" Count="3" MaxCount="3" /> <Item SlotNumber="17" Name="HP" Count="1" MaxCount="3" /> <Item SlotNumber="18" Name="MP" Count="1" MaxCount="3" /> </ItemDB> | cs |
<요소>
<필드이름 정보1 정보2 정보3 정보4.../>
<필드이름 정보1 정보2 정보3 정보4.../>
</요소>
이런식으로 구성이 되어있는데, 이것을 스크립트로 만들어 내보낼 것이다.
XML문서를 만드는 스크립트의 흐름은 이렇다.
1. XML문서를 하나 만든다.
2. 요소를 하나 만든다.
3. 만든 요소를 XML문서에 첨부한다.
여기까지 코드를 짜면 XML문서는
---------------------------------
<요소>
</요소>
---------------------------------
까지 생성이 된다.
4. 필드(요소)를 생성.
5. 필드(요소)의 내용을 셋팅.
6. 첫 번째 요소의 방금만든 필드(요소)를 첨부.
까지 하면 위의 완성된 XML문서가 완성되며,
마지막으로 XML를 정해진 경로로 내보내면 저장은 끝난다.
코드를 한 번 보도록 하자.
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 | using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Xml; // sealed을 사용하여 다른 클래스가 상속되지 못하도록 함. public sealed class ItemIO { public static void SaveDate() { // 인벤토리에서 슬롯을 관리해주는 리스트를 받아온다. List<GameObject> item = ObjManager.Call().IV.AllSlot; XmlDocument XmlDoc = new XmlDocument(); // XML문서 생성. XmlElement XmlEl = XmlDoc.CreateElement("ItemDB"); // 요소 생성. XmlDoc.AppendChild(XmlEl); // 요소를 XML문서에 첨부. // 리스트의 총 크기(슬롯의 개수.) int Count = item.Count; for (int i = 0; i < Count; i++) { // 슬롯 리스트에서 슬롯을 하나씩 꺼내온다. Slot itemInfo = item[i].GetComponent<Slot>(); // 슬롯이 비어있으면 저장할 필요가 없으므로 넘긴다. if (!itemInfo.isSlots()) continue; // 필드(요소)를 생성. XmlElement ElementSetting = XmlDoc.CreateElement("Item"); // 필드(요소)의 내용을 셋팅. ElementSetting.SetAttribute("SlotNumber", i.ToString()); // n번째 슬롯에 아이템. ElementSetting.SetAttribute("Name", itemInfo.ItemReturn().Name); // 아이템의 이름. ElementSetting.SetAttribute("Count", itemInfo.slot.Count.ToString()); // 아이템의 개수. (ex: 현 슬롯에 겹쳐진 아이템 10개임.) ElementSetting.SetAttribute("MaxCount", itemInfo.ItemReturn().MaxCount.ToString()); // 아이템을 겹칠수 있는 한계. XmlEl.AppendChild(ElementSetting); // ItemDB요소에 위의 셋팅한 요소를 문서에 첨부. } // XML문서로 내보낸다. 인자로는 문서를 내보낼 경로. XmlDoc.Save(Application.dataPath + "/Save/InventoryData.xml"); } } | cs |
1 | using System.Xml; | cs |
필수는 아니지만 각 함수를 사용할 때 System.Xml을 쓰는건 효율이 떨어지므로 using해둡시다.
1 | XmlDocument XmlDoc = new XmlDocument(); | cs |
Document는 문서라는 뜻으로 XML문서를 만듭니다.
1 | XmlElement XmlEl = XmlDoc.CreateElement("ItemDB"); | cs |
Element는 요소,성분이라는 뜻으로 새로운 요소를 인자의 이름으로 만든다.
이 구문에서 XML문서의 <ItemDB> </ItemDB>가 완성된다.
1 | XmlDoc.AppendChild(XmlEl); | cs |
Append는 첨부라는 뜻으로 요소를 XML문서에 첨부하는데 사용한다.
쭉 보면
1. XML문서를 만들고
2. <ItemDB> </ItemDB>라는 요소를 만들어서
3. XML문서에 첨부.
라는 것이 된다.
그 다음 for문을 돌려 필드를 생성시켜야 하는데, 이것은 무엇에 대한 for문일까?
우리는 인벤토리에 각 슬롯이 가지고있는 아이템에 대한 정보를 저장하는 것이다
만약 슬롯이 30개 존재한다고 하면 for문을 30개 돌아 각 슬롯이 가진 정보를 필드에 옮겨 저장하는 것이다.
슬롯 개수에 대한 정보는 인벤토리 스크립트가 가지고 있으므로 가져와서
슬롯의 숫자만큼 for문을 돌면 된다.
for문을 돌때 슬롯에 아무것도 존재하지 않는다면 저장할 필요가 없으므로 continue해준다.
여기서 우리가 저장할 내용은 이렇다.
1. 슬롯의 번호
2. 아이템의 이름.
3. 아이템의 개수.
4. 아이템을 겹칠수 있는 한계 개수.
이렇게 4개에 대한 정보를 저장해야 한다.
슬롯의 번호를 저장하는 이유는
아이템이 2번째 칸에 있고, 게임을 껏다 켰을 때 그 아이템은 여전히 2번째 칸에 존재 해야한다.
Load할때 슬롯의 번호를 모르고 있다면 몇번째 슬롯에 아이템정보를 가져와야할지 알지 못하기 때문이다.
아무튼
for문을 돌면서
1 | XmlElement ElementSetting = XmlDoc.CreateElement("Item"); | cs |
또 하나의 필드(요소)를 생성한다. 이름은 "Item"이다.
이 필드(요소)에 위의 4가지 정보를 셋팅해준다.
1 2 3 4 | ElementSetting.SetAttribute("SlotNumber", i.ToString()); // n번째 슬롯에 아이템. ElementSetting.SetAttribute("Name", itemInfo.ItemReturn().Name); // 아이템의 이름. ElementSetting.SetAttribute("Count", itemInfo.slot.Count.ToString()); // 아이템의 개수. (ex: 현 슬롯에 겹쳐진 아이템 10개임.) ElementSetting.SetAttribute("MaxCount", itemInfo.ItemReturn().MaxCount.ToString()); // 아이템을 겹칠수 있는 한계. | cs |
※ 모두 문자열로 저장시켜야 한다.
Item이라는 필드에 위의 4가지 정보가 추가되면
이 추가된 정보를 첫 번째 요소인 "ItemDB"에 첨부시켜야 한다.
1 | XmlEl.AppendChild(ElementSetting); | cs |
이렇게 기본적인 XML문서가 완성된다.
이제 이 XML문서를 내보내면 저장이 되는 것이다.
1 | XmlDoc.Save(Application.dataPath + "/Save/InventoryData.xml"); | cs |
Application.dataPath는 현재 자신의 유니티 프로젝트에 Assets폴더까지의 경로를 반환해준다.
필자같은경우 Assets폴더 안에 Save라는 폴더를 만들었고 그 안에 XML문서가 저장되는데,
문서가 저장될때 이름이 InventoryData.xml이다.
'Unity3D > Project' 카테고리의 다른 글
[Unity3D] 헥사게임 만들기 첫 번째 - 리소스 준비하기 및 캔버스 크기 설정. (0) | 2018.02.11 |
---|---|
[Unity3D] 인벤토리 [Part 4] - Load (3) | 2017.04.24 |
[Unity3D] 인벤토리 [Part 3] - Item Drag & Swap (5) | 2017.04.13 |
[Unity3D] 인벤토리 [Part 2] - Item Add (13) | 2017.04.12 |
[Unity3D] 인벤토리 [Part 1] - Inventory UI (5) | 2017.04.07 |