유니티 RPG - 48. 플레이어 데이터 저장 및 로드
Intro
이번 포스팅에서는 플레이어의 데이터를 Load 하는 데이터매니저 클래스에
플레이어 데이터를 Save 하는 기능까지 추가해보았습니다.
PlayerData.Json
기존의 데이터파일에는 플레이어 능력치(Status)만 저장을 했었고
또한 플레이어 캐릭터가 하나가아닌 여러캐릭터를 저장할 수 있도록 배열형식으로 저장했었습니다.
우선 단일 플레이어 캐릭터의 데이터를 저장하기위한 방식으로 변경하였고,
Status 뿐 아니라 Position 데이터도 함께 저장할 수 있도록 하였습니다.
{
"Status": {
"maxHp": 1000.0,
"curHp": 780.0,
"maxMp": 1000.0,
"curMp": 1000.0,
"speed": 0.0,
"rotateSpeed": 10.0,
"damage": 5.0,
"defense": 0.0,
"gold": 5000
},
"Position": {
"posX": 0,
"posY": 0,
"posZ": 0
}
}
PlayerDataDTO 클래스
저장할 데이터가 늘어났으므로 PlayerDataDTO 클래스도 수정하였습니다.
[System.Serializable]
public class PlayerDataDTO
{
public StatusDTO Status;
public PositionDTO Position;
[System.Serializable]
// 스탯 정보
public class StatusDTO
{
public float maxHp; // 최대체력
public float curHp; // 현재체력
public float maxMp; // 최대마나
public float curMp; // 현재마나
public float speed; // 이동속도
public float rotateSpeed; // 회전속도
public float damage; // 기본 공격력
public float defense; // 기본 방어력
public int gold; // 보유 골드
}
[System.Serializable]
// 위치 정보
public class PositionDTO
{
public float posX;
public float posY;
public float posZ;
}
}
-
한 캐릭터의 데이터만을 저장할것이므로 기존의 List 형식으로 저장하던방식을 수정하였습니다.
-
플레이어 위치데이터를 저장하기위하여 PositionDTO를 만들었습니다.
- 데이터의 성질에따라 나누어 관리함으로써 유지보수와 확장성을 고려하였습니다.
PlayerData 클래스
현재는 DTO -> PlayerData 로의 변환만이 가능합니다.
데이터 저장을 위해서는 현재의 PlayerData 를 DTO로 변환하는 작업이 필요합니다.
PlayerData 클래스에서 DTO로의 변환 메서드를 제공합니다.
/*
PlayerData
- 플레이어 데이터 정보
- 플레이어 데이터와 관련된 기능 함수 제공
- UsePortion() : 포션사용시 포션종류에 따른 능력치 변화
- EquipItem() : 장비장착시 장비종류에 따른 능력치 변화
- UnequipItem(): 장비해제시 장비종류에 따른 능력치 변화
- GetDamaged() : 피격당한 데미지에따른 능력치 변화
- UseGold() : 골드사용에 따른 보유 골드 변화
*/
public class PlayerData
{
#region ** Player Status **
[SerializeField] private float maxHp;
[SerializeField] private float curHp;
[SerializeField] private float maxMp;
[SerializeField] private float curMp;
[SerializeField] private float speed;
[SerializeField] private float rotateSpeed;
[SerializeField] private float damage;
[SerializeField] private float defense;
[SerializeField] private int gold;
#endregion
#region ** Player Position **
[SerializeField] private float posX;
[SerializeField] private float posY;
[SerializeField] private float posZ;
#endregion
#region ** Properties **
public float MaxHp => maxHp;
public float CurHp => curHp;
public float MaxMp => maxMp;
public float CurMp => curMp;
public float Speed => speed;
public float RotateSpeed => rotateSpeed;
public float Damage => damage;
public float Defense => defense;
public int Gold => gold;
public float PosX => posX;
public float PosY => posY;
public float PosZ => posZ;
#endregion
// 플레이어 데이터 초기화
public PlayerData(PlayerDataDTO dto)
{
this.maxHp = dto.Status.maxHp;
this.curHp = dto.Status.curHp;
this.maxMp = dto.Status.maxMp;
this.curMp = dto.Status.curMp;
this.speed = dto.Status.speed;
this.rotateSpeed = dto.Status.rotateSpeed;
this.damage = dto.Status.damage;
this.defense = dto.Status.defense;
this.gold = dto.Status.gold;
this.posX = dto.Position.posX;
this.posY = dto.Position.posY;
this.posZ = dto.Position.posZ;
}
// PlayerData -> DTO
public PlayerDataDTO ToDTO()
{
return new PlayerDataDTO
{
Status = new PlayerDataDTO.StatusDTO
{
maxHp = this.maxHp,
curHp = this.curHp,
maxMp = this.maxMp,
curMp = this.curMp,
speed = this.speed,
rotateSpeed = this.rotateSpeed,
damage = this.damage,
defense = this.defense,
gold = this.gold
},
Position = new PlayerDataDTO.PositionDTO
{
// 플레이어 현재 위치
posX = GameManager.Instance.player.transform.position.x,
posY = GameManager.Instance.player.transform.position.y,
posZ = GameManager.Instance.player.transform.position.z
}
};
}
}
DataManager 클래스
DataManager 클래스에서는 PlayerDataDTO 클래스의 변경에따른 코드수정과,
데이터 Save를 위한 함수를 작성하였습니다.
// DataManager.cs
// 데이터 저장
public void SaveData<T>(T data, string fileName)
{
string filePath = Path.Combine(Application.persistentDataPath, fileName + ".json");
string jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
File.WriteAllText(filePath, jsonData);
}
// 플레이어 데이터 불러오기
private PlayerData LoadPlayerData()
{
if(File.Exists(playerDataPath))
{
string jsonData = File.ReadAllText(playerDataPath);
var playerDTO = JsonConvert.DeserializeObject<PlayerDataDTO>(jsonData);
if (playerDTO != null && playerDTO.Status != null && playerDTO.Position != null)
{
return new PlayerData(playerDTO);
}
else
{
Debug.LogWarning("PlayerData.json 파일에 Status 또는 Position 정보가 없음.");
return null;
}
}
else
{
Debug.LogWarning("PlayerData.json 파일이 없음.");
return null;
}
}
// 플레이어 데이터 저장
public void SavePlayerData()
{
PlayerDataDTO dto = playerData.ToDTO();
SaveData(dto, "PlayerData");
}
-
LoadPlayerData() : PlayerData 의 각 항목(Status, Position)이 유효한지 확인하여 PlayerData를 초기화합니다.
-
SavePlayerData() : 현재 플레이어 데이터를 저장합니다.
-
SaveData() : 데이터와 저장할 파일이름을 받아 데이터를 저장합니다.
- 제네릭으로 작성하여 플레이어 데이터뿐 아니라 모든 종류의 데이터를 저장할 수 있도록 하였습니다.
댓글남기기