-
비동기 데이터 저장Unity/제로부터 구현 2024. 7. 25. 16:22728x90
데이터 파일 관리하기
1. 플레이어가 가지고있는 고유 데이터와 맵별로 가지고있는 데이터를 분리
2. 플레이어 데이터와 맵 데이터를 가지고있는 클래스를 비동기로 저장하기
1. 플레이어가 가지고있는 고유 데이터와 맵별로 가지고있는 데이터를 분리
맵마다 가지고 있는 데이터들이 모두 상이하기 때문에 하나의 데이터파일에서 관리하는 것이 가독성이나 필요한 데이터를 찾는 과정이 더 복잡할 것 같아 플레이어 데이터와 분리.
더보기더보기더보기[Serializable] public class SaveFileData { public SerializableSaveMapDataDictionary<string, MapSaveData> SerializableSaveMapDataDictionary; public PlayerSaveData _PlayerSaveData; public SaveFileData(SerializableSaveMapDataDictionary<string, MapSaveData> SerializableSaveMapDataDictionary, PlayerSaveData _PlayerSaveData) { this.SerializableSaveMapDataDictionary = SerializableSaveMapDataDictionary; this._PlayerSaveData = _PlayerSaveData; } }
JsonUtility 에는 딕셔너리를 json 으로 파싱해주는 기능은 없기 때문에 키와 벨류를 리스트로 받아 놓고 딕셔너리 처럼 사용할 수 있게
SerializableSaveMapDataDictionary 라는 클래스를 만듦,
Newtonsoft의 Json.NET 를 사용해 복잡한 구조를 한번에 json 화 시킬 수도 있지만 라이브러리를 사용하지않고 직접 관리 하고 싶었음
더보기더보기더보기[Serializable] public class SerializableSaveMapDataDictionary<TKey, TValue> { [SerializeField] private List<TKey> keys = new List<TKey>(); [SerializeField] private List<TValue> values = new List<TValue>(); public void Add(TKey key, TValue value) { if (keys.Contains(key)) { Debug.LogWarning($"Key {key} already exists. Value will not be added."); return; } keys.Add(key); values.Add(value); } public Dictionary<TKey, TValue> ToDictionary() { Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(); for (int i = 0; i < keys.Count; i++) { if (dictionary.ContainsKey(keys[i])) { Debug.LogWarning($"Duplicate key {keys[i]} found during ToDictionary conversion. Skipping."); continue; } dictionary[keys[i]] = values[i]; } return dictionary; } public void FromDictionary(Dictionary<TKey, TValue> dictionary) { keys.Clear(); values.Clear(); foreach (var kvp in dictionary) { keys.Add(kvp.Key); values.Add(kvp.Value); } } }
PlayerSaveData는 말그대로 플레이어가 가지고 있는 고유 데이터들을 모아놓은 클래스,
맵과 관련된 데이터는 SerializableSaveMapDataDictionary 를 통해 가져오고
플레이어와 관련된 데이터는 PlayerSaveData로
2. 플레이어 데이터와 맵 데이터를 가지고있는 클래스를 비동기로 저장하기
더보기더보기더보기public async Task Save_SaveFile() { _SaveFileData.SerializableSaveMapDataDictionary.FromDictionary(dic); string json = JsonUtility.ToJson(_SaveFileData); //File.WriteAllText(filePath, json); await WriteTextAsync(filePath, json); Debug.Log("Data Saved to " + filePath); } private async Task WriteTextAsync(string path, string content) { byte[] encodedText = Encoding.UTF8.GetBytes(content); using (FileStream sourceStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)) { await sourceStream.WriteAsync(encodedText, 0, encodedText.Length); }; }
Task 를 통해 비동기로 데이터를 처리하게 해주었는데 처음에는 File.WriteAllText() 을 통해 간단하게 json 파일을 저장해줬는데, 데이터 저장은 비동기로 처리하는게 더 좋을 것 같아서 FileStream 으로 비동기 처리를 해줌.
FileStream은 더 복잡하고 세밀한 파일 작업을 필요로 할 때 사용
- 파일에 대한 다양한 읽기 및 쓰기 작업을 지원
- 버퍼 크기를 지정
- 시스템 자원을 직접적으로 관리할 수 있으며, IDisposable 인터페이스를 구현하여 자원 해제를 자동으로 처리
File.WriteAllText()는 간단한 문자열 기록 작업을 빠르게 수행할 때 적합
- 내부적으로 FileStream을 사용하지만, 파일 열기와 닫기 작업을 자동으로 처리
- 파일 스트림의 세부 사항을 신경 쓸 필요가 없음
using 문의 경우 자원관리를 간편하게 해주는 구문으로 FileStream 을 생성하고 사용 후 자동으로 해당 객체를 정리해줌.
1.FileStream 객체가 using 블록 안에 생성
2.sourceStream 객체로 비동기 데이터 처리,
- new FileStream(경로, 파일 생성 모드, 파일 액세스 권한, 파일을 열 때 다른 프로세스가 해당 파일에 대해 어떤 액세스를 할 수 있는지를 지정,파일을 읽거나 쓸 때 사용하는 버퍼의 크기를 바이트 단위로 지정,비동기 작업을 사용할지 여부
3.using 블록이 끝나면 sourceStream 객체의 Dispose 메서드가 자동으로 호출, FileStream이 사용하는 파일 핸들을 닫고, 관련된 시스템 자원을 해제.
728x90'Unity > 제로부터 구현' 카테고리의 다른 글
Pentagon Balance UI 제작하기 (0) 2024.06.07 AssetPreview.GetAssetPreview() 로 얻은 텍스쳐 배경 투명하게 만들어서 저장하기 (0) 2024.04.27 MiniMap (2D) (0) 2024.01.21 Cinemachine 을 사용한 카메라 이동 범위 제한 (2D) (0) 2024.01.16 플레이어의 정보를 로컬 저장소에 저장하기 (PlayerPrebs) (0) 2023.12.24