ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 비동기 데이터 저장
    Unity/제로부터 구현 2024. 7. 25. 16:22
    728x90

    데이터 파일 관리하기

    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
Designed by Tistory.