내일배움캠프 Unity 78일차 TIL - 팀 9와 4분의 3 - 개발일지

Wooooo·2024년 2월 16일
0

내일배움캠프Unity

목록 보기
80/94

[오늘의 키워드]

  1. 몬스터 웨이브 클래스 구조 변경
  2. 아티팩트가 몬스터 웨이브 요청
  3. 트러블 슈팅

[몬스터 웨이브 클래스 구조 변경]

기존에는 매일 밤이되면 GameManager가 몬스터웨이브를 시작하는 구조로 작성돼있었다.
이제는 Artifact 클래스가 몬스터 웨이브와 통신할 것이기 때문에 MosnterWave 클래스의 구조를 살짝 변경했다.

그리고, MonsterWave 클래스가 해야할 것만 같은 일을 GameManager에서 하고 있었기 때문에, 리팩토링도 살짝했다.

기존 코드

GameManager.cs

    private void SpawnMonster()
    {
        int cnt = 1;

        if (Season.CurrentValue >= 0f)
        {
            for (int i = 0; i < cnt; ++i)
                MonsterWave.AddOverFlowedMonster(FireIsland.Spawn());
        }
        else
        {
            for (int i = 0; i < cnt; ++i)
                MonsterWave.AddOverFlowedMonster(IceIsland.Spawn());
        }
    }

    private void StartMonsterWave()
    {
        CoroutineManagement.Instance.StartCoroutine(MonsterWaveCoroutine());
    }

    private IEnumerator MonsterWaveCoroutine()
    {
        var delay = UnityEngine.Random.Range(0.0f, 60.0f);
        yield return new WaitForSeconds(delay);
        MonsterWave.Start();
    }

변경 코드

MonsterWave.cs

    public void Start()
    {
    	// 몬스터 웨이브 시작
    }
    
    public void Start(float delayTime)
    {
        CoroutineManagement.Instance.StartCoroutine(MonsterWaveCoroutine(delayTime));
    }

    private IEnumerator MonsterWaveCoroutine(float delayTime)
    {
        yield return new WaitForSeconds(delayTime);
        Start();
    }

게임매니저가 랜덤한 지연시간만큼 뒤에 몬스터웨이브를 시작하는 기능을 갖고 있었는데, MosnterWave 클래스의 Start 메서드를 오버로딩하여 지연하여 시작할 수 있도록 구조를 변경했다.


[아티팩트가 몬스터 웨이브 요청]

코드

Artifact.cs

    public void SetInfo(Island island, Vector3 pos, Transform root, ArtifactData data, float? currentHP = null)
    {
    	...
    
        _dayCycle = Managers.Game.DayCycle;
        _dayCycle.OnEveningCame += SpawnOverflowedMonster;
    }
    
    public void SpawnOverflowedMonster()
    {
        Managers.Game.MonsterWave.AddOverFlowedMonster(_island.Spawn());
    }

    public void DestroyArtifact()
    {
    	...
        
        _dayCycle.OnEveningCame -= SpawnOverflowedMonster;
        OnDestroy?.Invoke(this);
        Destroy(gameObject);
    }

아티팩트가 몬스터 웨이브 클래스에게 생성될 몬스터를 추가할 수 있게 했다.

매일 저녁, 자신의 속성 (자신이 속한 섬)에 알맞는 몬스터를 소환하고, 해당 몬스터를 몬스터 웨이브에게 OverFlowedMonster로 설정하도록 했다.

OverFlowedMonster란, 생성되어 있는 몬스터 중 몬스터 웨이브가 시작되면 플레이어에게 달려들게 되는 몬스터다.
몬스터 웨이브는 OverFlowedMonster를 컬렉션으로 관리하며, 웨이브가 시작되면 컬렉션 안에 있는 몬스터들을 플레이어 주변으로 텔레포트 시킨다음 달려들게 한다.


[트러블 슈팅]

싸우던 몬스터가 몬스터 웨이브에게 불려가는 현상

바로 위에서 설명한 OverFlowedMonster의 설명만 들으면 바로 알아차릴 수 있는 문제가 있다.

아티팩트에 의해 생성된 몬스터는 OverFlowedMonster고, 밤이 되면 몬스터웨이브에 의해 플레이어 시야 밖으로 텔레포트 된다.

그런데 지금은 이미 플레이어 시야 안에 있는지를 걸러주지 않고 텔레포트 시키기 때문에, 플레이어와 치고받던 몬스터가 밤이되면 갑자기 텔레포트된다. (플레이어 입장에선 사라지는 것 처럼 느껴질 것이다.)

기존 코드

MonsterWave.cs

        while(waveMonsters.Count != 0)
        {
            var point = wavePoints.Pop();
            var monster = waveMonsters.Pop().GetComponent<Monster>();
            monster.NavMeshAgent.Warp(point);
            monster.SetBerserkMode();
            monster.SetIsland(null);
            monsters.Add(monster);
        }

변경 코드

MonsterWave.cs

        while(waveMonsters.Count != 0)
        {
            var point = wavePoints.Pop();
            var monster = waveMonsters.Pop().GetComponent<Monster>();
            if (!monster.GetCurrentChunkActive())
                monster.NavMeshAgent.Warp(point);
            monster.SetBerserkMode();
            monster.SetIsland(null);
            monsters.Add(monster);
        }

비활성화된 청크에 있는 몬스터만 워프시키도록 변경했다.

ManagementedObject와 MonsterWave

Monster 클래스는 생성 시 ManagementedObject 컴포넌트를 추가하여 자신의 렌더러와 콜라이더, Monster Behaviour를 관리하도록 하고 있다.

자신이 위치한 청크의 활성화 여부에 따라 각종 컴포넌트를 껐다 키는 방식이다.
따라서 플레이어와 먼 거리에 있는 몬스터들은 Update 메서드의 호출이나 물리연산, 렌더링 등을 하지 않도록 관리하고 있다.

하지만 MonsterWave는 비활성화된 청크에 있는 몬스터들을 플레이어 근처로 텔레포트 시킨다.
이 과정에서 텔레포트된 몬스터는 각종 컴포넌트가 꺼져있는 상태로 유지되고, 플레이어가 다른 청크로 이동하기 전까지 그 상태를 유지한다.

따라서 몬스터를 워프 시킨 후, ManagementedObject에게 컴포넌트 상태를 스위칭하도록 요청했다.

하지만 오류가 났다. 몬스터 웨이브는 기존에 생성돼있던 몬스터만 워프시키는 것이 아니라 자체적으로 생성한 몬스터를 워프시키기도 하는데, Monster 컴포넌트는 Start 메서드에서 MangementedObject를 AddComponent하기 때문에, 생성하자 마자 바로 워프시키는 지금의 구조에선 ManagementedObject가 아직 게임오브젝트에 등록되기 전이라 null 에러가 났다.

이 부분은 간단하게 널 체크 만으로 해결 가능했다.

변경 코드

MonsterWave.cs

        while(waveMonsters.Count != 0)
        {
            var point = wavePoints.Pop();
            var monster = waveMonsters.Pop().GetComponent<Monster>();
            if (!monster.GetCurrentChunkActive())
            {
                monster.NavMeshAgent.Warp(point);
                monster.GetComponent<ManagementedObject>()?.SwitchEnabled();
            }
            monster.SetBerserkMode();
            monster.SetIsland(null);
            monsters.Add(monster);
        }
profile
game developer

0개의 댓글