본문 바로가기
스파르타 내배캠

스파르타 내배캠 Unity 3기 9일차

by LemongO 2024. 1. 4.

음..

 

 

개인과제 선택 요구사항 마지막 - 세이브구현...

 

사실 어디서부터 모르고 뭘 모르는지 잘 모르겠다. (그냥 다 모르겠다.)

그래서 하면서 느꼈던 것들을 적다 보면 갈피를 잡지 않을까?

 


시도 1. BinaryFormatter [사용되지 않음]

세이브를 하기 위해 게임이 종료되는 시점에 Player의 정보를 받아야 하는데

text로 player의 정보를 일일이 받으면 비효율적이니, 객체를 받아서 한 번에 처리해 보고자 했다.

그 수단으로 먼저 BinaryFormatter를 써보기로 했다.

 

FileStream fs = new FileStream("C:\\Users\\User\\Documents\\GitHub\\SpatranProject\\playerData.dat", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();

bf.Serialize(fs, player);
fs.Close();

 

문제는 BinaryFormatter를 쓰고 싶어도 더 이상 사용을 못 한다는 것이었다.

 

쓸 수가 없네?

 

https://learn.microsoft.com/ko-kr/dotnet/fundamentals/syslib-diagnostics/syslib0011

 

SYSLIB0011 경고 - .NET

컴파일 시간 경고 SYSLIB0011을 생성하는 사용되지 않음에 대해 알아봅니다.

learn.microsoft.com

보안 취약성BinaryFormatter으로 인해 다음 API는 .NET 5에서 사용되지 않는 것으로 표시되었습니다.

 

라고 한다...

 

 


 

 

그래서 대체재로 Json을 써보기로 했다.


시도2. Json

먼저 파일의 경로와 이름을 지정해주고

string fileName = "playerData.json";
string saveFolderName = "C:\\Users\\User\\Documents\\GitHub\\SpartanProject";
string filePath = Path.Combine(saveFolderName, fileName);

 

 

세이브 함수를 만들어 주었다.

static void SavePlayer(Player player, string filePath)
{            
    string playerSaveData = JsonSerializer.Serialize(player);
    File.WriteAllText(filePath, playerSaveData);

    Console.WriteLine("데이터가 저장되었습니다.");
}

'JsonSerializer.Serialize' 는 JSON 형식의 문자열로 객체를 직렬화하는 데 사용되는 .NET 언어(예: C#)의 메서드입니다.

'File.WriteAllText' 는 .NET Framework 및 .NET Core에서 제공되는 메서드로, 지정된 파일에 텍스트를 쓰는 데 사용됩니다.

라고하는데...

 

쉽게 말해서 객체의 정보들을 json 형식의 문자열로 변환 해주고,

지정된 경로에 json 파일을 만들어 해당 문자열을 쓰는 방식이라는 말이겠지...?

 

실제로 코드를 실행 해보면

 

메모장으로 열었을 때

 

정상적으로 저장이 된 것을 확인했다.

근데 이름이 이스케이프 문자열로 저장이 됐다.

한글로 보고싶으면 다음 메서드를 추가해주면 된다고 한다.

 

playerSaveData = Regex.Unescape(playerSaveData);

 

한글로 잘 나온다.

 

하지만 한 줄로 나열돼 있는게 가독성이 떨어진다.

이를 해결하기 위해선 옵션을 추가해 Serialize 매개변수로 전달하면 된다고 한다.

JsonSerializerOptions options = new JsonSerializerOptions() { WriteIndented = true};
string playerSaveData = JsonSerializer.Serialize(player, options);

 

 

깔끔해졌다

 

이제 세이브를 했으니 로드를 구현해보자.

 

static Player LoadPlayer(string filePath)
{
    if (File.Exists(filePath))
    {
        Console.WriteLine("데이터가 존재합니다.");
        string playerData = File.ReadAllText(filePath);                  
        Player loadedPlayer = JsonSerializer.Deserialize<Player>(playerData);
        return loadedPlayer;
    }
    else
        return new Player(Define.PlayerClass.Worrior);
}

 

filePath에 data 정보가 있는 json파일이 있으면 <Player> 타입으로 역직렬화를 해 플레이어를 반환하고,

파일이 없다면 새로운 플레이어를 생성하도록 해줬다.

 

실행을 해보자.

 

예상밖의 일이 일어나고 말았다.

예외가 생겼는데 생성자의 매개변수 이름이 속성이나 필드 이름과 같아야 한다고 한다.

 

// 기존의 코드
public Player(PlayerClass playerClass)
{
    Lv = 1;
    Name = "르탄이";
    m_Class = playerClass;
    Atk = 10;
    Def = 5;
    Hp = 100;
    MaxHp = 100;
    Gold = 1500;
}

// 변경 코드
public Player(PlayerClass m_Class)
{
    Lv = 1;
    Name = "르탄이";
    this.m_Class = m_Class;
    Atk = 10;
    Def = 5;
    Hp = 100;
    MaxHp = 100;
    Gold = 1500;
}

 

매개변수 이름을 수정 후 다시 실행해보자.

 

정상 작동된다.