3 분 소요

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() : 데이터와 저장할 파일이름을 받아 데이터를 저장합니다.

    • 제네릭으로 작성하여 플레이어 데이터뿐 아니라 모든 종류의 데이터를 저장할 수 있도록 하였습니다.

테스트 영상

댓글남기기