● 게임 저장
도전과제 중 하나인 게임 저장하기를 구현하기 위해 Newtonsoft.Json을 사용하기로 했다.
먼저, 상단의 프로젝트>Nuget프로젝트관리>NewtonsoftJson를 검색해 다운해준다.
using Newtonsoft.Json;
스크립트에 위 코드를 적으면 Json관련 코드를 쓸 수 있게된다.
DataManager를 Json으로 저장하고, 불러올때는 Json을 DataManager로 바꿔서 _Instance에 넣어줬다.
public void Save()
{
string dataManager = JsonConvert.SerializeObject(Instance);
File.WriteAllText(GetFilePath(), dataManager);
}
public void Load()
{
if (!File.Exists(GetFilePath()))
{
Instance.Initialize();
return;
}
else
{
string dataManager = File.ReadAllText(FILENAME);
_Instance = JsonConvert.DeserializeObject<DataManager>(dataManager);
_Instance.IsExistSaveData = true;
}
}
● 직렬화 오류 해결
코드를 다 작성하고 디버깅을 해봤는데 에러가 나왔다.
JSON 데이터를 TextRPG.Item 클래스의 IsEquipped 속성에 설정하는 과정에서 오류가 난것같았다.
IsEquipped은 프로퍼티로 _IsEquipped의 값을 가져오고 있었고, Json으로 저장할 필요가 없기 때문에
아래와 같이 [JsonIgnore] 를 써서 해결할 수 있었다.
[JsonIgnore]
public bool IsEquipped
{
get => _IsEquipped;
set
{
_IsEquipped = value;
UpdateEquipState();
}
}
오류는 고쳤지만 값이 저장되지않았다.
이유를 알아보니 public 값은 자동적으로 직렬화가 되지만, private는 아닌것같았다.
아래와 같이 [JsonProperty]을 써서 _IsEquipped를 저장할 수 있게 되었다.
[JsonProperty]
private bool _IsEquipped = false;
● 콘솔창이 닫혔을때 게임 저장
이 다음에는 저장할 타이밍을 찾아 저장을 구현하는것이였는데
콘솔창이 닫혔을때 저장하기로 하였다.
AppDomain.CurrentDomain.ProcessExit에 저장함수를 넣어주는것으로 구현하였다.
//프로그램이 종료되는 시점에 저장
AppDomain.CurrentDomain.ProcessExit += SaveData;
● 음악재생
음악을 재생 시켜보고 싶어서 SoundManager 를 작성해 구현해보기로 하였다.
방법이 세가지가 있었는데
- SoundPlayer
- NAudio
- PLib
다양한 포맷 지원하고 음향을 조절 할 수 있는 NAudio을 이용하기로 하였다.
NuGet 설치가 필요해 설치를 하고 using 을 적어주었다.
using NAudio.Wave;
if (!File.Exists(filePath))
{
Console.WriteLine("파일을 찾을 수 없습니다: " + filePath);
return;
}
using (var audioFile = new MediaFoundationReader(filePath))
using (var outputDevice = new DirectSoundOut())
{
outputDevice.Init(audioFile);
outputDevice.Play();
}
+ (수정) BGM이 한번만 재생되었기에 코드를 수정했다.
효과음 같은 경우는 위 코드를 사용하면 될것같다.
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sound", FILENAME_BGM);
if (!File.Exists(filePath))
{
Console.WriteLine("파일을 찾을 수 없습니다: " + filePath);
return;
}
var audioFile = new MediaFoundationReader(filePath);
var outputDevice = new DirectSoundOut();
outputDevice.Init(audioFile);
outputDevice.Play();
//람다 활용!!!
outputDevice.PlaybackStopped += (sender, args) =>
{
audioFile.Position = 0;
outputDevice.Play();
};
● 상대 경로로 파일 경로 설정
하지만 여기서 갑자기 든 생각이 있었다.
내가 쓰고 있는 파일경로는 "C:\Users~~~" 여서 다른사람 컴퓨터에서 음악 파일을 불러올떄
파일을 찾을 수 없다고 뜰것같았다.
그래서 파일 경로를 실행 파일 기준으로 상대 경로 사용하기로 하였다.
"Sound"라고 적은거는 Sound파일 안에서 음악 파일을 찾게 하도록 하기 위해서이다.
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"Sound",FILENAME_BGM);
똑같이 저장데이터 불러오기와 저장도 파일경로 코드를 변경해주었다.
● 음악 파일 폴더 위치 수정
하지만 파일을 찾을 수 없다고 나왔다.
AppDomain.CurrentDomain.BaseDirectory 의 경로를 보니
" ~~~\TextRPG\bin\Debug\net6.0 " 라고 나왔다.
파일을 저 안으로 옮겨 주니 음악은 잘 재생되었다!
● Action을 이용해 코드 중복 해결
강의 4주차에서 나온 Action을 이용해 중복된 코드를 정리하기로 했다.
여태까지는 클래스로 관리하고 있지않은 활동숫자를 입력 받았을때를 각각의 클래스에서 관리하고 있었다.
아래 Action을 ActionBase에서 선언해서
각각의 클래스에서 유호하지 않은 활동숫자를 입력 받았을 떄의 함수를 OnInputInvalidActionNumber에 대입했다.
public Action<int> OnInputInvalidActionNumber = delegate { };
InputNextAction안에 적는걸로 코드 중복 해결!!!
public void InputNextAction()
{
while (true)
{
DisplayNextAction();
Console.Write("\n원하시는 행동을 입력해주세요.\n>>");
if (int.TryParse(Console.ReadLine(), out int sceneNumber))
{
if (NextActions.ContainsKey(sceneNumber))
{
NextActions[sceneNumber].OnStart();
break;
}
OnInputInvalidActionNumber?.Invoke(sceneNumber);
}
else
{
PrintErrorMessage(0);
}
continue;
}
}
'과제' 카테고리의 다른 글
[Unity,C#] 메타버스 제작 과제 3일차 (0) | 2025.02.19 |
---|---|
[Unity,C#] 메타버스 제작 과제 2일차 (0) | 2025.02.18 |
[Unity,C#] 메타버스 제작 과제 1일차 (0) | 2025.02.17 |
[TextRPG-팀 프로젝트] 기반 설계 (0) | 2025.02.10 |
[TextRPG-팀 프로젝트] 데이터 관리,퀘스트 구현 (0) | 2025.02.10 |