팀 프로젝트 일일 개발 일지: JSON 데이터를 이용해 군 데이터에 연결하기

ggm-_-·2024년 12월 6일
0

TIL (Tody I Learn)

목록 보기
38/51

(금)2024.12.06 자 끄적끄적...
오랜만에 TIL 처음 쓰던 때처럼 TIL을 끄적끄적 작성해보겠다.

오늘도 팀 프로젝트 개발일지다..!

사실, 오늘 하루의 절반 가까이를 삽질을 한 것 같다.
영지 경영 + 전쟁 전략 시뮬레이션 게임을 만들기 위해, 여러개의 ai영지들의 정보와 플레이어 영지의 정보들을 저장하는 곳이 필요한데, 이를 만들기 위해, WorldDB라는 데이터 베이스를 만드려고 했었다.
여기에는 모든 영지의 정보와 기사들의 정보, 병종들의 정보 등 여러가지의 인 게임 중에 변하면서 저장해야 할 필요성이 있는 정보들을 JSON 형태로 저장할 계획이었다.
이렇게 한다면, 하나의 World를 Load할 때, 이 DB에 있는 정보만 빼서 사용하면 되겠다는 생각이었다.

그런데, 데이터 구조 전체를 한 번 리펙토링 하시면서 각 영지의 정보를 stage형태처럼 하나로 묶어서 정보를 저장하게 만드신다고 하였다.
사실, 어제도 얘기한 내용이긴 했지만, 그렇게 할 수도 있고, '이렇게 하겠다!' 라고 완벽하게 정해진 느낌은 아니였어서, 그렇게 아예 바꾸는 형식으로 가고 있는지를 알 지 못하였다. (그냥 이런 방향도 있는데 이건 어떠냐? 하면서 서로 의견 나누다가 흐지부지 끝난 느낌이었다. 내가 느끼기로는)

아무튼, 그래서 진행중이던 작업을 중단하고, 월드에 상관없이 그냥 임시로 데이터를 받아서 플레이어의 군대 데이터에 넣어주고, 이것을 토대로 로직을 구현하는 방향으로 가기로 결정했다. (실제 사용 데이터 구조와 연결하는 것은 나중으로 하고, 현재 만들어 놓은 데이터 테이블 구조를 가지고 전략 설정 및 전투 구현 로직 작성이 가능하도록 하는 것이 목표이다.)

JSON 데이터 가져오기

그래서, 다음과 같이 TempDomainData를 만들어서, 임시적으로 영지의 정보가 담긴 데이터들을 JSON에서 가져왔다. (정말 그냥 사용만 하기 위해)

  • TempDomainData.cs
using Newtonsoft.Json;
using System.IO;
using UnityEditor.PackageManager;
using UnityEngine;

// 임시 영지 데이터
public class TempDomainData : MonoBehaviour
{
    public DomainArray domainArray;
    public KnightDataArray knightDataArray;
    public UnitTypeDataArray unitTypeDataArray;
    public StrategyDataArray strategyDataArray;
    public UnitDivisionPositionDataaArray unitDivisionPositionDataArray;
    public UnitDivisionDataArray unitDivisionDataArray;
    public UnitDivisionRoleDataArray unitDivisionRoleDataArray;

    string dataPath = "JsonData/";
    private void Awake()
    {
        SetTempData();
    }
    public void SetTempData()
    {
        domainArray = JsonConvert.DeserializeObject<DomainArray>(LoadData("DomainDataTable"));
        knightDataArray = JsonConvert.DeserializeObject<KnightDataArray>(LoadData("KnightDataTable"));
        unitTypeDataArray = JsonConvert.DeserializeObject<UnitTypeDataArray>(LoadData("UnitTypeDataTable"));
        strategyDataArray = JsonConvert.DeserializeObject<StrategyDataArray>(LoadData("StrategyDataTable"));
        unitDivisionPositionDataArray = JsonConvert.DeserializeObject<UnitDivisionPositionDataaArray>(LoadData("UnitDivisionPositionDataTable"));
        unitDivisionDataArray = JsonConvert.DeserializeObject<UnitDivisionDataArray>(LoadData("UnitDivisionDataTable"));
        unitDivisionRoleDataArray = JsonConvert.DeserializeObject<UnitDivisionRoleDataArray>(LoadData("UnitDivisionRoleDataTable"));
    }
    public string LoadData(string fileName)
    {
        string loadDataPath = Path.Combine(dataPath, fileName);
        Debug.Log($"LoadDataPath: {loadDataPath}");

        TextAsset jsonTextAsset = Resources.Load<TextAsset>(loadDataPath);
        if (jsonTextAsset != null )
        {
            Debug.Log($"Load 성공!");
            return jsonTextAsset.text;
        }
        
        Debug.LogError($"{fileName} 데이터 없음.");
        return "";
    }
}

실제 영지의 군에 데이터 삽입하기

TempSetData를 만들어서, 이전에 DomainArmy에 만들어 놓은 기사, 병종, 전략, 부대임무 리스트에 데이터를 넣는 작업을 진행했다.
그리고, LogDomainArmyData메서드를 만들어서 데이터가 잘 들어갔는지 확인하는 작업도 진행했다.

  • DomainArmy.cs (& DomainArmy에 연결된 클래스들. 나중에 다른 cs폴더로 옮겨줄 것이다.)
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

// 군 전체 정보
public class DomainArmy : MonoBehaviour
{
    // 전략 세팅 시스템
    StrategySettingSystem strategySettingSystem = new StrategySettingSystem();

    TempDomainData tempDomainData;

    // 군 정보 리스트
    // 기사리스트
    List<Knight> knightList = new List<Knight>();
    // 병종리스트
    List<UnitType> unitTypeList = new List<UnitType>();
    // 전략리스트
    List<Strategy> strategyList = new List<Strategy>();
    // 부대임무리스트
    List<UnitDivisionRoleDataTable> unitDivisionRoleDataList = new List<UnitDivisionRoleDataTable>();

    public List<Knight> KnightList
    {
        get { return knightList; }
        private set { knightList = value; }
    }
    public List<UnitType> UnitTypeList
    {
        get { return unitTypeList; }
        private set { unitTypeList = value; }
    }
    public List<Strategy> StrategyList {
        get { return strategyList; } 
        set { strategyList = value; }
    }
    public List<UnitDivisionRoleDataTable> UnitDivisionRoleDataList
    {
        get { return unitDivisionRoleDataList; }
        set {  unitDivisionRoleDataList = value; }
    }
    private void Awake()
    {

    }
    private void Start()
    {
        if (TryGetComponent<TempDomainData>(out tempDomainData))
        {
            Debug.Log($"{typeof(TempDomainData)} 로드 성공!");
            TempSetData();
        }
        else
        {
            Debug.LogError("데이터 로드 실패!");
        }
        LogDomainArmyData();
    }

    public void TempSetData()
    {
        TempSetKnightList();
        TempSetUnitTypeList();
        TempSetStrategyList();
        TempSetUnitDivisionRoleDataList();
    }
    public void TempSetKnightList()
    {
        if (tempDomainData.knightDataArray == null || tempDomainData.knightDataArray.KnightDataTable == null)
        {
            Debug.LogError("knightDataArray or KnightDataTable is null!");
            return;
        }
        List<KnightDataTable> KnightDataTable = tempDomainData.knightDataArray.KnightDataTable;
        for (int i = 0; i < KnightDataTable.Count; i++)
        {
            //GameObject knightObj = new GameObject($"Knight_{i}");
            //Knight knight = knightObj.AddComponent<Knight>();
            //knight.SetKnightData(KnightDataTable[i]);
            //knightList.Add(knight);
            knightList.Add(new Knight(KnightDataTable[i]));
        }

    }
    public void TempSetUnitTypeList()
    {
        List<UnitTypeDataTable> unitTypeDataTable = tempDomainData.unitTypeDataArray.UnitTypeDataTable;
        for (int i = 0; i < unitTypeDataTable.Count; i++)
        {
            unitTypeList.Add(new UnitType(unitTypeDataTable[i]));
        }
    }
    public void TempSetStrategyList()
    {
        List<StrategyDataTable> strategyDataTable = tempDomainData.strategyDataArray.StrategyDataTable;
        for (int i = 0; i < strategyDataTable.Count; i++)
        {
            strategyList.Add(new Strategy(strategyDataTable[i]));
        }
    }
    public void TempSetUnitDivisionRoleDataList()
    {
        List<UnitDivisionRoleDataTable> unitDivisionRoleDataTable = tempDomainData.unitDivisionRoleDataArray.UnitDivisionRoleDataTable;
        for (int i = 0; i < unitDivisionRoleDataTable.Count; i++)
        {
            unitDivisionRoleDataList.Add(unitDivisionRoleDataTable[i]);
        }
    }

    public void LogDomainArmyData()
    {
        LogKnightData();
        LogUnitTypeData();
        LogStrategyData();
        LogUnitDivisionRoleData();
    }

    public void LogKnightData()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("기사 목록: ");
        for (int i = 0; i < KnightList.Count; i++)
        {
            sb.Append(KnightList[i].KnightData.NameKr);
            sb.Append(", ");
        }
        sb.Append("\n");
        Debug.Log(sb);
    }
    public void LogUnitTypeData()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("병종 목록: ");
        for (int i = 0; i < UnitTypeList.Count; i++)
        {
            sb.Append(UnitTypeList[i].UnitTypeData.NameKr);
            sb.Append(", ");
        }
        sb.Append("\n");
        Debug.Log(sb);
    }
    public void LogStrategyData()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("전략 목록: ");
        for (int i = 0; i < StrategyList.Count; i++)
        {
            sb.Append(StrategyList[i].StrategyData.Name);
            sb.Append(", ");
        }
        sb.Append("\n");
        Debug.Log(sb);
    }
    public void LogUnitDivisionRoleData()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("부대 임무 목록: ");
        for (int i = 0; i < UnitDivisionRoleDataList.Count; i++)
        {
            sb.Append(UnitDivisionRoleDataList[i].Name);
            sb.Append(", ");
        }
        sb.Append("\n");
        Debug.Log(sb);
    }

}
// 전략 설정 시스템
public class StrategySettingSystem : MonoBehaviour
{
    DomainArmy domainArmy;
    // 전략리스트 
    List<Strategy> strategyList;
    // 부대임무리스트
    List<UnitDivisionRoleDataTable> unitDivisionRoleDataList;

    Strategy currentStrategy;

    private void Start()
    {
        strategyList = domainArmy.StrategyList;
        unitDivisionRoleDataList = domainArmy.UnitDivisionRoleDataList;
    }
    // UI의 반응과 연계하여 전략 설정 및 저장
}
// 기사
public class Knight : MonoBehaviour
{
    // 기사 정보
    KnightDataTable knightData;

    public KnightDataTable KnightData
    {
        get { return knightData; }
        private set { knightData = value; }
    }

    public Knight (KnightDataTable knightData)
    {
        SetKnightData(knightData);
    }

    public void SetKnightData(KnightDataTable inputKnightData)
    {
        knightData = inputKnightData;
    }
}
// 병종
public class UnitType : MonoBehaviour
{
    // 병종 정보
    UnitTypeDataTable unitTypeData;

    public UnitTypeDataTable UnitTypeData
    {
        get { return unitTypeData; }
        private set { unitTypeData = value; }
    }

    public UnitType (UnitTypeDataTable unitTypeData)
    {
        SetUnitTypeData(unitTypeData);
    }
    public void SetUnitTypeData(UnitTypeDataTable inputUnitTypeData)
    {
        unitTypeData = inputUnitTypeData;
    }
}
// 전략
public class Strategy : MonoBehaviour
{
    // 전략 정보
    StrategyDataTable strategyData;

    public StrategyDataTable StrategyData
    {
        get { return strategyData; }
        private set { strategyData = value; }
    }

    public Strategy (StrategyDataTable strategyData)
    {
        SetStrategyData(strategyData);
    }

    public void SetStrategyData(StrategyDataTable inputStrategyData)
    {
        strategyData = inputStrategyData;
    }
}
// 부대
public class UnitDivision : MonoBehaviour
{
    // 부대 정보
    UnitDivisionDataTable unitDivisionData;

    public UnitDivisionDataTable UnitDivisionData
    {
        get { return unitDivisionData; }
        private set { unitDivisionData = value; }
    }

    public UnitDivision (UnitDivisionDataTable inputUnitDivisionData)
    {
        SetUnitDivisionData(unitDivisionData);
    }

    public void SetUnitDivisionData(UnitDivisionDataTable inputUnitDivisionData)
    {
        unitDivisionData = inputUnitDivisionData;
    }
}
// 부대 배치
public class UnitDivisionPosition : MonoBehaviour
{
    // 부대배치정보 - 부대(UnitDivision), 위치(Position), 회전(Rotation)
    UnitDivisionPositionDataTable unitDivisionPositionData;

    public UnitDivisionPositionDataTable UnitDivisionPositionData
    {
        get { return unitDivisionPositionData; }
        private set { unitDivisionPositionData = value; }
    }

    public UnitDivisionPosition (UnitDivisionPositionDataTable inputUnitDivisionPositionData)
    {
        SetUnitDivisionPositionData(unitDivisionPositionData);
    }

    public void SetUnitDivisionPositionData(UnitDivisionPositionDataTable inputUnitDivisionPositionData)
    {
        unitDivisionPositionData = inputUnitDivisionPositionData;
    }

    //UnitDivision unitDivision;
    //Vector3 position;
    //Vector3 rotation;
    // 부대의 병종과 수, 위치, 방향에 맞게 병사와 기사를 필드에 생성해주는 로직
}

// 병사
public class Soldier : MonoBehaviour
{
    // 부대의 UnitType의 데이터를 참조해서, 병사들이 전투중에 행동하는 로직에 사용
    UnitDivisionDataTable unitDivisionData;

    public UnitDivisionDataTable UnitDivisionData
    {
        get { return unitDivisionData; }
        private set { unitDivisionData = value; }
    }

    public Soldier (UnitDivisionDataTable inputUnitDivisionData)
    {
        SetSoldierData(unitDivisionData);
    }
    
    public void SetSoldierData(UnitDivisionDataTable inputUnitDivisionData)
    {
        unitDivisionData = inputUnitDivisionData;
    }
}

데이터 로드 및 확인 로그

이렇게 진행한다면, 다음과 같이 데이터 로드가 성공하고, 데이터 들어간 것을 확인할 수 있다.

  • 데이터 로드 로그
  • 데이터 확인 로그

+추가로 작업해야 할 사항

현재 기사, 병종, 전략, 부대 임무 리스트들을 new로 생성하고 있는데, MonoBehaviour는 new로 생성하면 MonoBehaviour의 기능을 사용하지 못하기 때문에, 쓰면 안된다고 한다.
그래서 GameObject를 만들어서 거기에 Component를 달아서 사용해야 할 듯하다.

다음과 같이 바꾸는 작업을 해야할 것이다.

  • 기존 코드
knightList.Add(new Knight(KnightDataTable[i]));
  • 바뀌게 될 코드
GameObject knightObj = new GameObject($"Knight_{i}");
Knight knight = knightObj.AddComponent<Knight>();
knight.SetKnightData(KnightDataTable[i]);
knightList.Add(knight);

오늘은 데이터를 관리하는 것을 고민하고, 직접 시스템에 부여하는 작업까지 해보았다. 물론, 처음에 한 고민이 이번 프로젝트에 안 쓰일지도 모르지만, 이러한 고민을 하며 구조를 짜보는 행위를 한 것 자체만으로 데이터 쪽을 보는 능력을 조금은 성장시킬 수 있었다,

조금만 더 속도를 높여서 작업할 수 있으면 좋겠지만, 열심히 한다고 한 것이 아직 이 정도이다. 아직 데이터 구조, 디자인 패턴, 서버와의 통신 등의 부분에서 자세히 알지 못하는 부분이 많아 속도가 느리지만, 해당 부분을 하나씩 공부하여 알게 되었을 땐, 굉장히 빠른 속도로 작업할 수 있을 것 같다.

이상이다.

오늘의 TIL 끝!

profile
미숙한 초보 게임 개발자

2개의 댓글

comment-user-thumbnail
2024년 12월 9일

좋습니다!!

1개의 답글