Unity_개발일지_45

홍신영·2024년 12월 23일
0

Unity

목록 보기
47/62

오늘 최종 프로젝트 중간 발표회를 가졌다.
사실 4주정도의 기간동안 진행했지만 진척도는 조금 아쉬움이 남는다.

남은 기간 얼마 되지는 않지만, 사이클은 나왔으니 화이팅해서 살 붙히기 작업에 들어가야 될 것 같다.

오늘은 중간발표회를 진행한 만큼 코드 리뷰를 해보려고 한다.

내가 구현한 부분은 던전관리 및 퍼즐이다.
처음에는 던전에 무슨 기능, 역할을 넣을지 생각이 잘 나지 않았다.

단순히 오브젝트 풀링을 사용하여 몬스터 생성 파괴를 관리해주면 되지 않을까 생각했었다.

하지만 기획단계에서 몬스터, 퍼즐은 던전에서 재생성(리스폰)되지 않고, 처음 수량만 생성하는게 좋을 것 같다고 이야기가 나와 오브젝트 풀링은 접어두고 어떻게 맵을 생성하고, 몬스터를 스폰 해줄지를 생각해 보았다.

현업에서는 이렇게 하지 않을까? 라고 생각하며 던전 데이터를 만들어 이에 맞게 생성해주어야 겠다는 생각이 들었다.

기획자가 던전에 대한 데이터를 입력해준다고 가정하고, 구글 시트를 이용하여 데이터를 작성해보자.

던전에서 다룰 데이터의 내용은 이러하다.
먼저 stageId는 딕셔너리에 키 값이 될 예정이다.
그리고 스테이지 이름이 될 ObjectName과
소환할 몬스터의 종류를 /로 나누어 적어주었고,
소환할 몬스터의 종류에 맞게 /로 수량도 입력해준다.

여기서 Monstercount의 데이터 타입을 string으로 한 것은 string으로 받아와서 /로 여러 종류의 몬스터를 받기 위함이다. 이는 후에 split'/'과 tryparse를 이용해서 int형으로 바꾸어 사용할 수 있다.

이렇게 되면 맵에 등장하는 몬스터의 종류와 수량을 가져올 수 있다.

여기서 잠깐!
몬스터의 스폰 위치는 어디있나?!

맞습니다. 처음에는 몬스터의 스폰위치도 int posX, posY, posZ로 몬스터의 생성 위치도 정해주었다. 하지만 이는 유니티 내에서 맵의 위치에 맞게 (12f, -30f, 120.3f)이런 식으로 위치를 일일히 정해주어야 하는 문제가 있었다.

그래서 몬스터의 생성 위치 지정은 편의성을 위해 Mapdata클래스를 만들어 List로 클래스를 만들어 소환될 위치들을 지정해주었다. 그리고 던전 매니저에 Transform을 반환하여 위치를 지정해주도록 하였다.

public List<Transform> monsterSpawnPoints;
    public Transform GetMonsterSpawnPoint()
    {
        if(monsterSpawnPoints == null || monsterSpawnPoints.Count == 0) return null;
        return monsterSpawnPoints[Random.Range(0, monsterSpawnPoints.Count)];
    }

위처럼 위치를 반환해줘 몬스터의 위치를 정해주었다.

다음은 구글 시트 데이터를 json으로 바꾸어주었다.
이 부분은 시트 데이터를 json으로 바꾸어주는 패키지를 활용해 변환해주었다.

json데이터를 이제 c#에서 사용할 수 있도록 해주자.

[System.Serializable]
public class MonsterSpawnData
{
    public string SpawnMonster;
    public string MonsterCount;

    public MonsterSpawnData(string spawnMonster, string monsterCount)
    {
        SpawnMonster = spawnMonster;
        MonsterCount = monsterCount;
    }
}

[System.Serializable]
public class MetaDungeonData : DataBase<MetaDungeonData>
{
    public string StageId;
    public string ObjectName;
    [SerializeField] private string SpawnMonster;
    [SerializeField] private string MonsterCount;
    public List<MonsterSpawnData> MonsterSpawnList = new List<MonsterSpawnData>();

    public override void SetData(MetaDungeonData metaData)
    {
        this.StageId = metaData.StageId;
        this.ObjectName = metaData.ObjectName;
        AddMonsterSpawnData(metaData.SpawnMonster, metaData.MonsterCount);
    }

    private void AddMonsterSpawnData(string spawnMonster, string monsterCount)
    {
        if (string.IsNullOrEmpty(spawnMonster) == false)
        {
            MonsterSpawnData monsterSpawnData = new MonsterSpawnData(spawnMonster, monsterCount);
            MonsterSpawnList.Add(monsterSpawnData);
        }
    }
}

다음과 같이 던전 데이터를 구성하였다.
시트에서 작성 해준 데이터들을 데이터 타입에 맞게 변수로 선언해주었고, 스테이지에 관련한 부분과 몬스터 스폰에 관련한 데이터를 나누어 주었다.
몬스터만 스폰 하는 경우가 있을 수 있고, 다르게 처리하고 싶을 수 있기에 나누어 주었다. 던전 매니저에서 맵과 몬스터 생성을 분리하여 생성하고 있기도 하다.

변수로 선언한 데이터들을 DataBase라는 클래스를 상속받아 SetData를 오버라이드 하여 데이터를 넣어주었다.
그리고 DataBaseList클래스가 DataBaseList를 상속 받게 하여 데이터 리스트를 재정의 하고, 딕셔너리에 저장해주었다.

이는 딕셔너리를 통해 키 값으로 스테이지 정보를 빠르고 편하게 가져오게 하기 위해 작성해주었다.

다음으로 이제 데이터 매니저로 json을 로드해주었다.

    private DungeonDataList dungeonDataList;
    public DungeonDataList DungeonDB => dungeonDataList ??= LoadData<DungeonDataList, DungeonDataList>("Dungeon", data =>
    {
        dungeonDataList = new DungeonDataList();
        dungeonDataList.SetData(data.Dungeon);
        return dungeonDataList;
    });
    private T LoadData<T, M>(string resourceKey, System.Func<M, T> customAction = null) where T : new()
    {
        TextAsset data = ResourceManager.Instance.LoadAsset<TextAsset>(resourceKey, eAssetType.JsonData);
        if (data != null)
        {
            Debug.Log($"JSON 파일 로드 성공: {resourceKey}");
            M MetaDataList = JsonUtility.FromJson<M>(data.text);
            var loadData = customAction.Invoke(MetaDataList);
            return loadData;
        }
        else
        {
            Debug.LogError($"{resourceKey} 데이터 불러오기 실패");
            return default;
        }
    }

로드가 완료되었고, 던전 매니저에서 스테이지 데이터를 받아 맵과 몬스터를 생성해주면 된다.

생성 전에 던전 매니저는 매니저니까 당연히 싱글톤? dontdestory?일줄 알았지만 다시 생각해보면 던전 매니저는 플레이어가 던전에 들어 갔을 때만 필요한 매니저이기에 싱글톤으로 구현하지 않았다. 하지만 전역 접근이 필요할 때가 있어 이를 게임 매니저를 통해 접근이 가능하도록 구현하였다.

그래서 던전 매니저는 게임 매니저로 부터 생성되고, 이어 던전 내에 존재하는 퍼즐 매니저는 던전 매니저에서 생성해 주도록 구현하였다.

던전 매니저가 생성되면 초기화 작업부터 해주었다.

    public void InitializeDungeon(string stageId)
    {
        PuzzleManager = new GameObject("PuzzleManager").AddComponent<PuzzleManager>();
        curStageId = stageId;
        MetaDungeonData stageData = DataManager.Instance.DungeonDB.LoadData(stageId);
        SpawnStageObjects(curStageId, stageData);
        Debug.Log("현재 스테이지: " + curStageId);
    }

여기에 들어갈 내용이 퍼즐 매니저를 생성해주는 것이고,
게임매니저로부터 넘겨받은 stageId를 (키값)을 curstage로 캐싱해주고,
데이터 매니저로부터 키 값을 이용해 스테이지 데이터를 불러오고,
마지막으로 맵과 몬스터를 스폰해주도록 하였다.

먼저 매개변수로 stageId를 전달받아, stageId로 리소스 매니저를 통해 맵을 로드해주었다.

그리고 맵은 0,0,0에 고정적으로 스폰되어도 되겠다고 생각이 들어 위치를 크게 잡아 주지는 않았다. 바로 instatiate해준다.

근데 지금 너무 졸리다

profile
게임 클라이언트 개발자

0개의 댓글