4부에서는 인벤토리에 들어 있는 아이템을 Json Data로 저장해 보겠습니다.
UniTask를 사용할 일이 없을 것 같아 3부에서 코루틴으로 사용해도 된다고 했었지만
파일 불러오기에서 사용해야 될 일이 있어 설치하셔야겠습니다.
https://github.com/Cysharp/UniTask
GitHub - Cysharp/UniTask: Provides an efficient allocation free async/await integration for Unity.
Provides an efficient allocation free async/await integration for Unity. - Cysharp/UniTask
github.com
위 링크로 가시면 UniTask를 설치하실 수 있습니다.
오늘도 여기저기 추가되는 코드가 있기에 집중해서 따로 오시기 바랍니다.
우선 인벤토리를 파일로 저장하기 위한 데이터 모델을 하나 만들겠습니다.
using System.Collections.Generic;
[System.Serializable]
public class InventoryModel
{
public List<string> invenItemID = new();
public List<int> invenArrayNumber = new();
public List<int> invenItemCount = new();
}
Json 파일로 저장해야 하기에 InventoryModel이 직열화 되어 있습니다.
invenItemID -> blue와 red 아이템을 만들 때 사용한 아이템의 ID가 저장됩니다.
invenArrayNumber -> 인벤토리에 아이템이 위치하고 있는 슬롯의 번호가 저장됩니다.
invenItemCount -> 아이템의 수량이 저장됩니다.
다시 InventoryManager.cs에 추가 코드입니다.
public void JsonDataInventory(Item item, int slotNumber, int itemCount)
{
var g = Instantiate(inventoryItem);
g.transform.SetParent(inventorySlots[slotNumber].transform);
g.transform.localScale = new Vector3(1, 1, 1);
g.SetActive(true);
g.GetComponent<InventoryItem>().InitialiseItem(item, itemCount);
}
게임을 시작한 후 Json Data를 불러와 인벤토리에 저장된 Data의 아이템을 배치하게 해 줍니다.
코드 설명은 따로 하지 않겠습니다. 아이템 Add 코드와 별반 다르지 않습니다.
다음은 DataManager.cs 에 추가 코드입니다.
[Header("아이템 목록")]
public Item[] items;
private string inventoryDataPath;
readonly string inventoryFileName = "inventory.json";
Item [] items; -> 아이템 목록입니다. 앞에서 만든 blue와 red아이템을 여기에 등록해 주세요.
그리고 추가되는 아이템이 있다면 그 아이템들도 여기 목록에 추가해 주셔야 합니다.
이 아이템 목록의 역할은 Json Data에서 불러온 아이템 ID와 비교해서
같은 아이템이 있다면 items에서 아이템의 데이터를 인벤토리로 넣어 주는 역할을 하게 됩니다.
inventoryDataPath -> Json 파일이 저장될 Path
inventoryFileName -> Json의 파일 이름입니다.
계속 DataManager.cs에 이어지는 추가 코드입니다.
private void Start()
{
#if UNITY_EDITOR
inventoryDataPath = Path.Combine(Application.dataPath, "JsonData", inventoryFileName);
#elif UNITY_ANDROID
inventoryDataPath = Path.Combine(Application.persistentDataPath , inventoryFileName);
#endif
if (File.Exists(inventoryDataPath))
// Json 데이터 불러오기
LoadData().Forget();
}
}
우선 유니티의 Project > Assets에 JsonData라는 폴더를 하나 만들어 주세요.
이곳에 파일이 저장되게 될 것입니다.
위 코드에서 Path를 얻는 방법이 두 가지가 나오는데 하나는 유니티 에디터 상에서의 Path
즉 방금 만든 JsonData 폴더의 위치를 받아 오는 것이고
두 번째는 안드로이드 일 때 Path를 받아 오는 방식입니다.
이건 공식과 같은 거라 그냥 이렇게 받아온다라고 알고 계시면 됩니다.
바로 밑 if 문의 역할은 Json 파일이 존재한다면 데이터를 불러옵니다.
private async UniTask LoadData()
{
InventoryModel inventoryModel;
inventoryModel = await DataFileLoad<InventoryModel>(inventoryDataPath);
if (inventoryModel != null)
{
for (int i = 0; i < inventoryModel.invenItemID.Count; i++)
{
var index = Array.FindIndex(items, item => item.itemID == inventoryModel.invenItemID[i]);
inventory.JsonDataInventory(items[index],
inventoryModel.invenArrayNumber[i],
inventoryModel.invenItemCount[i]
);
}
}
}
public void SaveData()
{
InventoryModel inventoryModel = new();
// 인벤토리 저장
if (inventory.inventorySlots.Count > 0)
{
for (int i = 0; i < inventory.inventorySlots.Count; i++)
{
var slotItem = inventory.inventorySlots[i].GetComponentInChildren<InventoryItem>();
if (slotItem != null)
{
inventoryModel.invenItemID.Add(slotItem.item.itemID);
inventoryModel.invenArrayNumber.Add(i);
inventoryModel.invenItemCount.Add(slotItem.count);
}
}
DataFileSave(inventoryModel, inventoryDataPath);
}
}
실제 Data를 파일로 저장하고 저장된 파일을 읽어오는 코드는 바로 밑에 있으니 참고하세요.
인벤토리 모델을 하나 생성 하고 DataFileLoad로 Json 데이터를 읽어와 inventoryModel에 넣어 줍니다.
불러온 Json Data의 Count에 맞게 for 문을 돌려 위에서 만든 items라는 아이템 목록의 아이템 ID와
불러온 Json Data Item ID를 비교 후 같은 ID가 있다면 items 목록의 index 값을 넘겨줍니다.
그럼 위에 InentoryManager에서 만든 JsonDataInventory 메서드를 이용해 해당 아이템을
인벤토리에 배치해 줍니다.
여기서 중요한 게 아이템을 저장할 때 여러 Slot 칸 중에 해당 아이템이 10번 Slot에 있었다면
여기서 아이템을 배치할 때도 역시 10번 Slot에 배치되어야 할 것입니다.
JsonDataInventory 메서드에서 이 기능이 그 역할을 해주고 있습니다.
생성된 아이템을 인벤토리 Slot 목록 중 invenArrayNumber 값을 이용해 해당 위치의 Slot 위치값을
생성된 아이템의 SetParent에 전달하게 되면 그 위치로 가게 되는 것입니다.
저장은 등록된 Slot 목록을 불러와 자식으로 있는 InventoryItem이 있는지 검사 후
해당 아이템의 Id와 슬롯의 위치값 그리고 수량을 인벤토리 모델에 넣어 파일로 저장하는 부분입니다.
public async UniTask<T> DataFileLoad<T>(string _path) where T : class
{
try
{
if (!File.Exists(_path))
{
return null;
}
using (var reader = new StreamReader(_path))
{
string content = await reader.ReadToEndAsync();
return JsonUtility.FromJson<T>(content);
}
}
catch (Exception ex)
{
Debug.LogError($"File Read Error: {ex.Message}");
return null;
}
}
public void DataFileSave<T>(T data, string _path) where T : class
{
try
{
string directoryPath = Path.GetDirectoryName(_path);
if (!Directory.Exists(directoryPath))
{
Debug.LogError($"Directory does not exist: {directoryPath}");
return;
}
string saveJsonData = JsonUtility.ToJson(data, true);
File.WriteAllText(_path, saveJsonData);
}
catch (Exception ex)
{
Debug.LogError($"File Save Error: {ex.Message}");
}
}
파일로 저장하고 불러오는 코드의 설명은 생략하겠습니다.
이것 역시 공식과 같은 것이라 그냥 붙여 넣기 하시면 되는 부분입니다.
다만 한 가지 메서드들이 제네릭 타입으로 되어 있습니다.
이건 향후에 게임데이터를 저장할 때 인벤토리 데이터만 저장할게 아니기에 여러 데이터 모델을
같이 사용해야 합니다. 그때를 위해 제네릭으로 받아 오는 것입니다.
사용 방법은 위 코드에도 있지만 다시 한번 적어 본다면
읽어 올 땐
데이터 모델 타입을 위 코드처럼 적어 주시면 됩니다.
데이터를 저장할 땐 모델 타입과 Path를 위 코드처럼 같이 넣어 주시면 됩니다.
마지막으로 작동이 잘되나 확인해 보겠습니다.
위 이미지처럼 Save Button을 하나 만들어 Click 이벤트에 DataManager의 SaveData 메서드와 연결해 주세요.
그리고 JsonData 폴더가 생성되어 있나 확인하신 후 게임을 플레이시키신 후
아이템을 생성하시고 Save 버튼을 눌러보시기 바랍니다
유니티 JsonData에 마우스 오른쪽 버튼을 클릭 후 Refresh를 클릭하시면 방금 저장된 Json Data가 보일 것입니다.
이렇게 저장되게 됩니다.
이제 이 데이터를 가지고 게임을 실행했을 때 제대로 불러와지는지 다시 확인해 보겠습니다.
위 JsonData에 맞게 Slot 0번 위치에 하나 그리고 슬롯 7번 위치에 하나씩 잘 표시되고 있네요
4부는 여기까지 하겠습니다.
5부에선 아이템을 클릭하면 해당 아이템의 정보가 표시되는 창과 아이템을 사용해서 소비되는 기능
다 사용된 아이템을 삭제하는 기능까지 만들어 보겠습니다.
'Unity' 카테고리의 다른 글
유니티 (Unity) - 실전 인벤토리 제작 (추가 기능) (4) | 2025.08.07 |
---|---|
유니티 (Unity) - 실전 인벤토리 제작 (5부) (4) | 2025.07.28 |
유니티 (Unity) - 실전 인벤토리 제작 (3부) (0) | 2025.07.25 |
유니티 (Unity) - 실전 인벤토리 제작 (2편) (0) | 2025.07.24 |
유니티 (Unity) - 실전 인벤토리 제작 (1편) (0) | 2025.07.24 |