Merge pull request #12 from Degulleo/DEG-23-세이브-로드-로직-구현
Deg 23 세이브 로드 로직 구현
This commit is contained in:
commit
39abb506da
8
Assets/KJM.meta
Normal file
8
Assets/KJM.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dbfd37452c39a544895c4f842901be82
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
BIN
Assets/KJM/KJM.unity
(Stored with Git LFS)
Normal file
BIN
Assets/KJM/KJM.unity
(Stored with Git LFS)
Normal file
Binary file not shown.
7
Assets/KJM/KJM.unity.meta
Normal file
7
Assets/KJM/KJM.unity.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fce4c0b08a429b64695c3c0aed06df0f
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
Assets/KJM/KJM_Test.meta
Normal file
8
Assets/KJM/KJM_Test.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cf313a0298660aa4db16ced680557810
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
43
Assets/KJM/KJM_Test/Save.cs
Normal file
43
Assets/KJM/KJM_Test/Save.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
// 던전 관련 저장 데이터
|
||||||
|
[Serializable]
|
||||||
|
public class DungeonSave
|
||||||
|
{
|
||||||
|
// 강화 수치
|
||||||
|
public int attackLevel;
|
||||||
|
public int attackSpeedLevel;
|
||||||
|
public int heartLevel;
|
||||||
|
public int moveSpeedLevel;
|
||||||
|
public int evasionTimeLevel;
|
||||||
|
|
||||||
|
// 현재 진행 중인 스테이지
|
||||||
|
public int stageLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 일상(자취방) 관련 저장 데이터
|
||||||
|
[Serializable]
|
||||||
|
public class HomeSave
|
||||||
|
{
|
||||||
|
// 일상 시간
|
||||||
|
public float time;
|
||||||
|
public int day;
|
||||||
|
|
||||||
|
// 체력 및 평판 수치
|
||||||
|
public float health;
|
||||||
|
public float reputation;
|
||||||
|
|
||||||
|
//이벤트
|
||||||
|
public bool isEvent;
|
||||||
|
public int mealCount;
|
||||||
|
public int houseworkCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 게임 전체 저장 구조
|
||||||
|
[Serializable]
|
||||||
|
public class Save
|
||||||
|
{
|
||||||
|
public HomeSave homeSave;
|
||||||
|
public DungeonSave dungeonSave;
|
||||||
|
}
|
11
Assets/KJM/KJM_Test/Save.cs.meta
Normal file
11
Assets/KJM/KJM_Test/Save.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 883ac325bc606014fa78662a7b7ec954
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
188
Assets/KJM/KJM_Test/SaveManager.cs
Normal file
188
Assets/KJM/KJM_Test/SaveManager.cs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using CI.QuickSave;
|
||||||
|
using Unity.VisualScripting;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
public class SaveManager : Singleton<SaveManager>
|
||||||
|
{
|
||||||
|
private const string SaveFolder = "QuickSave";
|
||||||
|
private string MainSaveFilePath => GetSavePath("Save_Main");
|
||||||
|
private string BackupSaveFilePath => GetSavePath("Save_Backup");
|
||||||
|
|
||||||
|
|
||||||
|
private Save mainSave;
|
||||||
|
private Save backupSave;
|
||||||
|
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
Load(); //저장된 메인,백업 세이브를 로드
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
if(JsonUtility.ToJson(mainSave) == JsonUtility.ToJson(StatManager.instance.ToSaveData())) //같은 상태는 저장되지 않음. 백업 덮어쓰기 방지.
|
||||||
|
return;
|
||||||
|
|
||||||
|
EnsureSaveExists();
|
||||||
|
|
||||||
|
backupSave = LoadMain(); //메인 세이브를 백업 세이브에 로드
|
||||||
|
SaveBackup(); //백업 세이브 저장
|
||||||
|
UpdateSaveInfo(); //세이브를 현재 정보로 업데이트
|
||||||
|
SaveMain(); //메인 세이브 저장
|
||||||
|
|
||||||
|
Debug.Log("세이브 되었습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load()
|
||||||
|
{
|
||||||
|
EnsureSaveExists();
|
||||||
|
|
||||||
|
mainSave = LoadMain();
|
||||||
|
backupSave = LoadBackup();
|
||||||
|
|
||||||
|
StatManager.instance.loadSaveData2StataManager(mainSave);
|
||||||
|
|
||||||
|
Debug.Log("메인 로드" + mainSave.homeSave.reputation); //임시 코드
|
||||||
|
Debug.Log("백업 로드" + backupSave.homeSave.reputation); //임시 코드
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateSaveInfo()
|
||||||
|
{
|
||||||
|
mainSave = StatManager.instance.ToSaveData(); //스탯을 관리하는 클래스에 선언된 스탯 업데이트 함수를 호출
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveMain()
|
||||||
|
{
|
||||||
|
QuickSaveWriter.Create("Save_Main")
|
||||||
|
.Write("Main", mainSave)
|
||||||
|
.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveBackup()
|
||||||
|
{
|
||||||
|
QuickSaveWriter.Create("Save_Backup")
|
||||||
|
.Write("Backup", backupSave)
|
||||||
|
.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Save LoadMain()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return QuickSaveReader.Create("Save_Main").Read<Save>("Main");
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Main 세이브 로드 실패: " + e.Message);
|
||||||
|
|
||||||
|
// 백업 시도
|
||||||
|
if (QuickSaveRaw.Exists(BackupSaveFilePath))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("백업 세이브로 복구 시도");
|
||||||
|
return LoadBackup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 백업도 없을 경우 새 세이브 생성
|
||||||
|
Debug.LogError("세이브 전체 손상 → 새 세이브 생성");
|
||||||
|
return CreateNewSave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Save LoadBackup()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return QuickSaveReader.Create("Save_Backup").Read<Save>("Backup");
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Backup 세이브 로드 실패: " + e.Message);
|
||||||
|
|
||||||
|
// 백업 시도
|
||||||
|
if (QuickSaveRaw.Exists(MainSaveFilePath))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("메인 세이브로 복구 시도");
|
||||||
|
return LoadMain();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 메인도 없을 경우 새 세이브 생성
|
||||||
|
Debug.LogError("세이브 전체 손상 → 새 세이브 생성");
|
||||||
|
return CreateNewSave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//더미 세이브 파일 생성
|
||||||
|
private Save CreateNewSave()
|
||||||
|
{
|
||||||
|
var fresh = StatManager.instance.ToSaveData();
|
||||||
|
SaveMain();
|
||||||
|
SaveBackup();
|
||||||
|
return fresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
//세이브 파일의 존재 여부 확인
|
||||||
|
private void EnsureSaveExists()
|
||||||
|
{
|
||||||
|
if (!QuickSaveRaw.Exists(MainSaveFilePath)) // Save_Main 파일이 없을때
|
||||||
|
{
|
||||||
|
if (!QuickSaveRaw.Exists(BackupSaveFilePath)) //Save_Backup 파일도 존재하지 않을때
|
||||||
|
{
|
||||||
|
UpdateSaveInfo();
|
||||||
|
SaveMain(); //Save_Main 파일 생성
|
||||||
|
backupSave = LoadMain();
|
||||||
|
SaveBackup(); //Save_Backup 파일 생성
|
||||||
|
|
||||||
|
Debug.Log("세이브가 존재하지 않아 새로운 세이브를 생성했습니다.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mainSave = LoadBackup(); //백업을 메인으로 로드.
|
||||||
|
SaveMain();
|
||||||
|
Debug.Log("메인을 백업 세이브로 로드했습니다.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!QuickSaveRaw.Exists(BackupSaveFilePath)) //Save_Backup 파일이 없을떄
|
||||||
|
{
|
||||||
|
backupSave = LoadMain();
|
||||||
|
SaveBackup();
|
||||||
|
Debug.Log("백업을 메인 세이브로 로드했습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//세이브 파일 디렉토리 확인
|
||||||
|
private string GetSavePath(string fileNameWithoutExt)
|
||||||
|
{
|
||||||
|
string directory = Path.Combine(Application.persistentDataPath, SaveFolder);
|
||||||
|
|
||||||
|
// 폴더가 없다면 생성
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
|
||||||
|
return Path.Combine(directory, fileNameWithoutExt + ".json");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 씬이 바뀔 때 마다 자동저장
|
||||||
|
protected override void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||||
|
{
|
||||||
|
StartCoroutine(SaveAfterOneFrame());
|
||||||
|
}
|
||||||
|
|
||||||
|
//Start함수 이후에 호출되도록 1프레임 지연
|
||||||
|
IEnumerator SaveAfterOneFrame()
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
Save();
|
||||||
|
Debug.Log("자동저장 되었습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
11
Assets/KJM/KJM_Test/SaveManager.cs.meta
Normal file
11
Assets/KJM/KJM_Test/SaveManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9c85bf88c19d95947bc288da9dfd85bf
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
120
Assets/KJM/KJM_Test/StatManager.cs
Normal file
120
Assets/KJM/KJM_Test/StatManager.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 테스트용 임시 클래스
|
||||||
|
/// </summary>
|
||||||
|
public class StatManager : MonoBehaviour
|
||||||
|
{
|
||||||
|
public static StatManager instance;
|
||||||
|
|
||||||
|
public int attackLevel;
|
||||||
|
public int attackSpeedLevel;
|
||||||
|
public int heartLevel;
|
||||||
|
public int moveSpeedLevel;
|
||||||
|
public int evasionTimeLevel;
|
||||||
|
public int stageLevel;
|
||||||
|
|
||||||
|
public float time;
|
||||||
|
public int day;
|
||||||
|
public float health;
|
||||||
|
public float reputation;
|
||||||
|
|
||||||
|
public bool isEvent; //Todo 이벤트 여부 및 관련 조건들 추가
|
||||||
|
public int mealCount;
|
||||||
|
public int houseworkCount;
|
||||||
|
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 스탯값 변화
|
||||||
|
/// </summary>
|
||||||
|
public void ChangeValue()
|
||||||
|
{
|
||||||
|
float floatValue = Random.Range(0f, 2f);
|
||||||
|
Debug.Log(floatValue);
|
||||||
|
int intValue = Random.Range(0, 10);
|
||||||
|
Debug.Log(intValue);
|
||||||
|
|
||||||
|
attackLevel = intValue;
|
||||||
|
attackSpeedLevel = intValue;
|
||||||
|
heartLevel = intValue;
|
||||||
|
moveSpeedLevel = intValue;
|
||||||
|
evasionTimeLevel = intValue;
|
||||||
|
stageLevel = intValue;
|
||||||
|
|
||||||
|
|
||||||
|
time = floatValue;
|
||||||
|
day = intValue;
|
||||||
|
health = floatValue;
|
||||||
|
reputation = floatValue;
|
||||||
|
|
||||||
|
isEvent = false;
|
||||||
|
mealCount = intValue;
|
||||||
|
houseworkCount = intValue;
|
||||||
|
|
||||||
|
Debug.Log("ChangeValue");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 스탯값 반환
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Save ToSaveData()
|
||||||
|
{
|
||||||
|
return new Save
|
||||||
|
{
|
||||||
|
dungeonSave = new DungeonSave
|
||||||
|
{
|
||||||
|
attackLevel = this.attackLevel,
|
||||||
|
attackSpeedLevel = this.attackSpeedLevel,
|
||||||
|
heartLevel = this.heartLevel,
|
||||||
|
moveSpeedLevel = this.moveSpeedLevel,
|
||||||
|
evasionTimeLevel = this.evasionTimeLevel,
|
||||||
|
stageLevel = this.stageLevel
|
||||||
|
},
|
||||||
|
homeSave = new HomeSave
|
||||||
|
{
|
||||||
|
time = this.time,
|
||||||
|
day = this.day,
|
||||||
|
health = this.health,
|
||||||
|
reputation = this.reputation,
|
||||||
|
isEvent = false,
|
||||||
|
mealCount = this.mealCount,
|
||||||
|
houseworkCount = this.houseworkCount,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadSaveData2StataManager(Save saveData)
|
||||||
|
{
|
||||||
|
attackLevel = saveData.dungeonSave.attackLevel;
|
||||||
|
attackSpeedLevel = saveData.dungeonSave.attackSpeedLevel;
|
||||||
|
heartLevel = saveData.dungeonSave.heartLevel;
|
||||||
|
moveSpeedLevel = saveData.dungeonSave.moveSpeedLevel;
|
||||||
|
evasionTimeLevel = saveData.dungeonSave.evasionTimeLevel;
|
||||||
|
stageLevel = saveData.dungeonSave.stageLevel;
|
||||||
|
|
||||||
|
time = saveData.homeSave.time;
|
||||||
|
day = saveData.homeSave.day;
|
||||||
|
health = saveData.homeSave.health;
|
||||||
|
reputation = saveData.homeSave.reputation;
|
||||||
|
isEvent = saveData.homeSave.isEvent;
|
||||||
|
mealCount = saveData.homeSave.mealCount;
|
||||||
|
houseworkCount = saveData.homeSave.houseworkCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SceneChange()
|
||||||
|
{
|
||||||
|
SceneManager.LoadScene("Main");
|
||||||
|
}
|
||||||
|
}
|
11
Assets/KJM/KJM_Test/StatManager.cs.meta
Normal file
11
Assets/KJM/KJM_Test/StatManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: afa35303e7c5e6141b05a11a7b5233ce
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
Assets/Scripts/Save.meta
Normal file
8
Assets/Scripts/Save.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0bc3d5a0f81acf64b850cc1570498ebc
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
x
Reference in New Issue
Block a user