[Unity][3D-Game] Tower Defense Game (25)

suhan0304·2023년 12월 30일
0
post-thumbnail

강의영상 (27)


개발

레벨 UNROCK 기능 구현

Level Selector Scene에서 레벨 1을 클리어해야 레벨 2이 언락되고 레벨 2를 클리어해야 레벨 3이 해금되도록 레벨 해금 기능을 구현해보자.

버튼 잠금

LevelSelector.cs

public Button[] levelButtons;

public void Start()
{
    for (int i = 0; i < levelButtons.Length; i++)
    {
        levelButtons[i].interactable = false; //시작하면 일단 모든 버튼은 상호작용 불가 (클릭안됨)
    }
}

위와 같이 버튼을 초기화해놓고 인스펙터에서 레벨 버튼들을 배열에 추가해준다.

이제 버튼이 interactable 상태일 때 다른 버튼의 모양을 가지도록 애니메이션을 수정한다. Button 애니메이션 컨트롤러에서 Disabled 애니메이션을 수정한다.

이 때 까먹지말고 Normal에서 줄여놓은 alpha 값을 다시 원상복귀 시키는 애니메이션을 추가한다.

실행해보면 모든 버튼이 Disabled에서 조정한 애니메이션 효과를 적용받아 투명해지고 클릭이 안되는 상태로 변한 것을 확인할 수 있다.

레벨 활성화

현재 진행가능한 레벨까지 버튼을 사용가능하도록 활성화 시키도록 한다.

LevelSelector.cs

public void Start()
{
    int levelReached = PlayerPrefs.GetInt("levelReached", 1); //값이 있으면 levelReached 가져오기, 없으면 1을 가져오기

    for (int i = 0; i < levelButtons.Length; i++)
    {
        if ( i + 1 > levelReached )
            levelButtons[i].interactable = false; //시작하면 일단 모든 버튼은 상호작용 불가 (클릭안됨)
    }
}

위와 같이 버튼을 비활성화 해주면 기존에 도달했던 레벨까지는 버튼이 비활성화되지 않고 그 위 레벨의 버튼든만 비활성화된다. PlayerPrefs에 levelReached가 없으면 가져오는 값이 레벨 1이므로 실행 시에 레벨 1 버튼만 활성화 되어있는 것을 확인할 수 있다.

레벨 클리어 구현

WaveSpawner에서 waves.Length 만큼 wave를 모두 진행했다면 레벨이 클리어 된 것이고 더 높은 레벨을 진행할 수 있도록 LevelReached를 업데이트하도록 구현한다.

WaveSpawner.cs

IEnumerator SpawnWave() //코루틴
{
    PlayerStats.Rounds++;

    Wave wave = waves[waveIndex];

    for (int i = 0; i < wave.count; i++)  //웨이브 레벨만큼 몬스터 소한
    {
        SpawnEnemy(wave.enemy);
        yield return new WaitForSeconds(1f / wave.rate);
    }

    waveIndex++;//웨이브가 올때마다 레벨업

    if (waveIndex == waves.Length)
    {
        gameManager.WinLevel(); //레벨 클리어 
        this.enabled = false; //WaveSpawner 스크립트를 비활성화
    }
}

GameManager.cs

public string nextLevel = "Level02";
public int levelToUnrock = 2;

public SceneFader sceneFader;

public void WinLevel()
{
    Debug.Log("LEVEL WON!");
    PlayerPrefs.SetInt("levelReached", levelToUnrock);
    sceneFader.FadeTo(nextLevel);
}

인스펙터에서 SceneFader를 초기화해준다.

위 코드를 설명하면 WaveSpawner에서 모든 Wave를 클리어하면 WinLevel 함수가 실행되고, 해당 함수에서는 Log를 한 번 출력하고 levelReached 값을 정해둔 levelToUnrock으로 설정해주고 다음 레벨 Scene으로 FadeTo로 넘어가는 함수이다.

추가적으로 Level03 장면을 복사해서 붙여넣고 Level02의 GameManager를 다음과 같이 수정하면 Level02 클리어 시에도 Level03을 진행할 수 있다.

각 장면마다 WaveSpanwer에 GameManager를 연결시켜주어야한다.

로직 오류 수정

기존에는 Enemy가 생성되면 EnemiesAlive Enemy 오브젝트를 죽이면 EnemiesAlive가 감소되고 0이면 다음 웨이브로 넘어가는식으로 구현했는데 이 때 웨이브가 시작할 때 Enemy를 instantiate하기 전에 EnemisAlive의 0을 인식해버리는 문제가 있는데 해당 문제를 다음과 같이 수정해서 고친다.

WaveSpawner.cs

IEnumerator SpawnWave() //코루틴
{
    PlayerStats.Rounds++;

    Wave wave = waves[waveIndex];

    EnemiesAlive = wave.count;

    for (int i = 0; i < wave.count; i++)  //웨이브 레벨만큼 몬스터 소한
    {
        SpawnEnemy(wave.enemy);
        yield return new WaitForSeconds(1f / wave.rate);
    }

    waveIndex++;//웨이브가 올때마다 레벨업

    if (waveIndex == waves.Length)
    {
        gameManager.WinLevel(); //레벨 클리어 
        this.enabled = false; //WaveSpawner 스크립트를 비활성화
    }
}

void SpawnEnemy(GameObject enemy)
{
    //미리 지정해둔 스폰 포인트에서 몬스터를 복사해서 소환
    Instantiate(enemy, spawnPoint.position, spawnPoint.rotation);
}

위와 같이 Enemy를 스폰하기 전에 EnemiesAlive를 그냥 wave의 count 값으로 설정해버리는 방식으로 수정해서 오류를 픽스할 수 있다.


결과물

profile
Be Honest, Be Harder, Be Stronger

0개의 댓글