- 주제
>> 게임 정보(인벤토리, 컨디션)를 Jason으로 저장하고 불러오는 기능을 담당하는 클래스 생성
>> 싱글톤 패턴으로 관리하여 확장성 높이기
>> 인벤토리 데이터를 관리하는 스크립트에 저장 관련 메서드 추가
- 공부내용
1. 저장기능 클래스 생성(SaveManager.cs)
-게임 정보를 쉽게 저장하여 씬 전환이나 게임 종료 후 다시 시작해도 게임 정보를 불러올 수 있도록 확장
명사형 한글 주석
-저장경로: savePath
Application.persistentDataPath는 각 플랫폼에 맞는 저장 경로를 반환
-저장 데이터: SaveData
JsonUtility.ToJson 메서드를 사용하여 객체를 JSON 문자열로 변환하고, 이를 파일에 저장
-데이터 불러오기: LoadData
파일이 존재하면 내용을 읽어 JsonUtility.FromJson 메서드를 통해 객체로 변환
using System.IO;
using UnityEngine;
// 저장 관리 클래스
public class SaveManager : MonoBehaviour
{
// 싱글톤 인스턴스
public static SaveManager Instance { get; private set; }
// 저장 경로
private string savePath;
private void Awake()
{
// 싱글톤 패턴 설정
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject); // 씬이 전환되도 파괴되지 않게 설정
savePath = Path.Combine(Application.persistentDataPath, "saveData.json"); // 저장 경로 설정
}
else
{
Destroy(gameObject); // 이미 인스턴스가 있으면 파괴
}
}
// 데이터 저장 메서드
public void SaveData(SaveData data)
{
string json = JsonUtility.ToJson(data, true); // 데이터를 JSON 형식으로 변환
File.WriteAllText(savePath, json); // 파일에 JSON 데이터 저장
}
// 데이터 불러오기 메서드
public SaveData LoadData()
{
if (File.Exists(savePath))
{
string json = File.ReadAllText(savePath); // 파일에서 JSON 데이터 읽기
return JsonUtility.FromJson<SaveData>(json); // JSON 데이터를 SaveData 객체로 변환
}
return null; // 파일이 없으면 null 반환
}
}
// 저장 데이터 클래스
[System.Serializable]
public class SaveData
{
public List<ItemData> items; // 아이템 목록
public List<int> quantities; // 아이템 수량 목록
}
2. UIInventory.cs (저장메서드 추가)
- Awake 메서드: 초기 설정을 담당합니다. 슬롯들을 찾고, 버튼들을 초기화합니다.
- Start 메서드: 버튼 클릭 이벤트를 설정하고, 슬롯을 초기화하며, 인벤토리 데이터를 불러옵니다.
- OnApplicationQuit 및 OnDestroy 메서드: 게임 종료 또는 씬 전환 시 인벤토리 데이터를 저장합니다.
- SaveInventory 메서드: 현재 인벤토리 데이터를 SaveData 객체에 저장하고, SaveManager를 통해 파일에 저장합니다.
- LoadInventory 메서드: SaveManager를 통해 파일에서 데이터를 불러와 슬롯에 설정합니다.
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class UIInventory : MonoBehaviour
{
// 설명 인덱스 열거형
private enum eDescriptionIndex
{
ITEM_NAME, // 아이템 이름
ITEM_DESCRIPTION, // 아이템 설명
STAT_NAME, // 스탯 이름
STAT_VALUE // 스탯 값
}
// 버튼 인덱스 열거형
private enum eBtnIndex
{
USE_BTN, // 사용 버튼
DROP_BTN, // 버리기 버튼
EQUIP_BTN, // 장착 버튼
UNEQUIP_BTN, // 장착 해제 버튼
INSTALL_BTN // 설치 버튼
}
public event Action InventoryRefresh; // 인벤토리 갱신 이벤트
[Header("Inventory")]
private Transform holdings; // 아이템 슬롯들
public List<TextMeshProUGUI> selectedDescriptions; // 선택된 아이템 설명들
public List<GameObject> invenBtns = new List<GameObject>(); // 인벤토리 버튼들
public ItemSlot[] slots { get; private set; } // 아이템 슬롯 배열
private ItemSlot selectedSlot; // 선택된 슬롯
private PlayerCondition condition; // 플레이어 상태
private Transform dropPosition; // 아이템 버리는 위치
private void Awake()
{
holdings = transform.Find("Holdings"); // Holdings 오브젝트 찾기
foreach (Transform transform in transform.Find("ItemInfo"))
{
if (transform.TryGetComponent(out TextMeshProUGUI component))
selectedDescriptions.Add(component); // ItemInfo에서 TextMeshProUGUI 컴포넌트 찾기
}
foreach (Transform transform in transform.Find("InvenBtns"))
{
invenBtns.Add(transform.gameObject); // InvenBtns에서 버튼 오브젝트들 찾기
}
}
private void Start()
{
invenBtns[(int)eBtnIndex.USE_BTN].GetComponent<Button>().onClick.AddListener(OnUseBtn);
invenBtns[(int)eBtnIndex.DROP_BTN].GetComponent<Button>().onClick.AddListener(OnDropBtn);
invenBtns[(int)eBtnIndex.EQUIP_BTN].GetComponent<Button>().onClick.AddListener(OnEquipBtn);
invenBtns[(int)eBtnIndex.UNEQUIP_BTN].GetComponent<Button>().onClick.AddListener(OnUnequipBtn);
invenBtns[(int)eBtnIndex.INSTALL_BTN].GetComponent<Button>().onClick.AddListener(OnInstallBtn);
// 슬롯 초기화
slots = new ItemSlot[holdings.childCount];
for (int i = 0; i < slots.Length; i++)
{
slots[i] = holdings.GetChild(i).GetComponent<ItemSlot>();
slots[i].inventory = this;
slots[i].slotIndex = i;
slots[i].Clear();
}
CharacterManager.Instance.Player.addItem += AddItem;
condition = CharacterManager.Instance.Player.condition;
dropPosition = CharacterManager.Instance.Player.dropPosition;
ClearSelectedItemWindow();
UpdateUI();
// 인벤토리 불러오기
LoadInventory();
}
private void OnApplicationQuit()
{
SaveInventory(); // 게임 종료 시 인벤토리 저장
}
private void OnDestroy()
{
SaveInventory(); // 씬 전환 시 인벤토리 저장
}
// 인벤토리 저장 메서드
public void SaveInventory()
{
SaveData saveData = new SaveData();
saveData.items = new List<ItemData>();
saveData.quantities = new List<int>();
foreach (var slot in slots)
{
if (slot.item != null)
{
saveData.items.Add(slot.item); // 아이템 데이터 추가
saveData.quantities.Add(slot.quantity); // 아이템 수량 추가
}
}
SaveManager.Instance.SaveData(saveData); // 저장 관리 클래스에 데이터 저장 요청
}
// 인벤토리 불러오기 메서드
public void LoadInventory()
{
SaveData saveData = SaveManager.Instance.LoadData(); // 저장 관리 클래스에서 데이터 불러오기 요청
if (saveData != null)
{
for (int i = 0; i < saveData.items.Count; i++)
{
ItemSlot emptySlot = GetEmptySlot(); // 빈 슬롯 찾기
if (emptySlot != null)
{
emptySlot.item = saveData.items[i]; // 아이템 데이터 설정
emptySlot.quantity = saveData.quantities[i]; // 아이템 수량 설정
}
}
UpdateUI(); // UI 업데이트
}
}
.....
public void UpdateUI()
{
for (int i = 0; i < slots.Length; i++)
{
if (slots[i].item != null)
{
slots[i].Set();
}
else
{
slots[i].Clear();
}
}
InventoryRefresh?.Invoke();
}
.....
'유니티' 카테고리의 다른 글
Day 40 - 상태머신(3D 방치형 게임 만들기 中) (0) | 2024.06.18 |
---|---|
Day 39 - SoundManager(오브젝트 풀에서 사운드 소스를 가져와 재생) (0) | 2024.06.12 |
Day 37 - 3D 건축 시스템 (0) | 2024.06.04 |
Day 36 - AI 네비게이션 (0) | 2024.06.03 |
Day 35 - JSON (게임 재시작 시, 최근 저장한 위치에서 시작) (0) | 2024.05.31 |