모름

06. Spawner System

이번 장에선 Delegate와 Action, Event를 배울 수 있었습니다. 더불어 추가로 Func까지 개념정리를 해야했습니다.

 

 

이번 에피소드에서 추가된 스크립트는 Spawer.cs였습니다. 그리고 Inner Class를 처음으로 만들어봤는데요. Wave라는 클래스를 내부적으로 하나 더 만들고 [System.Serializable] 이라는 함수로 에디터상에 보이게 해줬습니다.

 

    [System.Serializable]
    public class Wave {
        [Header("Spawn Setting")]
        public int enemyCount;
        public float timeBetweenSpawns;
    }

이렇게 해서 Spawner스크립트에선 위 Wave 클래스배열로 집어넣어 원하는 만큼의 웨이브를 유동적으로 만들 수 있게 했습니다. public Wave[] waves; 이런 식으로요.

 

그리고 적이 죽고나서 다음 웨이브로 이어질 때 Action을 사용했습니다. LivingEntity(체력관리 클래스)에서 Action을 이용해 체력이 다해 죽을때마다 OnDeath()이벤트를 발생시킵니다. Spawner에서 OnDeath이벤트를 받아 OnEnemyDeath()라는 함수를 발생시킵니다. 이렇게 자연스럽게 에너미의 죽음을 알 수 있습니다.

 

이러한 구성의 장점은 체력을 관리하는 곳에서 죽음 이벤트를 총괄 함으로서 나중에 플레이어가 죽을경우 똑같이 OnDeath이벤트를 보내주게됩니다. 그리고 OnPlayerDeath()라는 함수를 쉽고 체계적으로 만들어 사용할 수 있습니다.

 

추가 : Delegate, Event, Action, Func에 대한 개념이해

Action을 사용하려면 자연스럽게 위 네 가지 키워드에 대한 이해가 필요합니다. 깊게는 아니더라도 대략적으로 Delegate와 Event, Action, Func가 뭔지 알아야합니다. 저도 Action을 처음 써보면서 공부해보게 됐습니다.

 

public event System.Action OnDeath;

이렇게 Action OnDeath를 선언합니다. 역기서 Delegate인 Action은 OnDeath라는 이름의 메서드를 가리키게됩니다.

 

(LivingEntity.cs)

    protected void Die()
    {
        dead = true;
        if(OnDeath != null)
        {
            OnDeath();
        }
        GameObject.Destroy(gameObject);
    }

 

위와같이 Die()함수가 실행되고 죽었을때 OnDeath()함수를 실행시킵니다. 여기서 OnDeath()는 껍데기만 있는 빈 함수(무명메서드)입니다.

 

(Spawner.cs)

    private void Update()
    {
        if (enemiesRemainingToSpawn > 0 && Time.time > nextSpawnTime)
        {
            enemiesRemainingToSpawn--;
            nextSpawnTime = Time.time + currentWave.timeBetweenSpawns;

            Enemy spawnedEnemy = Instantiate(enemy, Vector3.zero, Quaternion.identity) as Enemy;
            spawnedEnemy.OnDeath += OnEnemyDeath;
        }
    }

    void OnEnemyDeath()
    {
        enemiesRemainingAlive--;
        if(enemiesRemainingAlive == 0)
        {
            NextWave();
        }
    }

그리고 OnDeath()함수는 Spawner클래스에서 항상 감시받고 있습니다. 그리고 OnDeath()함수에 Spawner.cs내의 함수인 OnEnemyDeath()를 넣어줌으로써 LivingEntity에서 OnDeath()함수가 실행되면 자연스럽게 Spawner에서 OnEnemyDeath()도 실행됨을 알 수 있습니다.

 

이렇게 Action을 이해하기 위해선 Delegate를 알아야합니다. Action이 C# 내부 라이브러리에 미리 만들어진 Delegate이기 때문입니다. 좋은 설명이 있어서 캡처한 내용을 공유하겠습니다. (Action, Func는 Delegate 안에 있는 친구들입니다)

 

위 내용은 Func와 Action의 차이를 설명합니다. 체계적으로 설명하기가 어렵네요. 어쨋든 사용예를 보여드리자면 아래와 같습니다.

 

Delegate를 쓸 경우

    public delegate void Death();
    public event Death OnDeath;

Death라는 델리게이트 변수를 만들고 이 Death라는 델리게이트가 OnDeath함수를 가리키게 만들었습니다.

 

Action을 쓸 경우

   public event System.Action OnDeath;

여기서 system은 생략해도 됩니다. Action이라는 델리게이트 변수에서 바로 OnDeath를 가리키고 있습니다. Action이라는 델리게이트 변수는 이용자들 편하게 쓰라고 C#내부 라이브러리에서 미리 만들어놓은 것들입니다. 델리게이트를 쓰고 싶을 때마다 델리게이트 변수를 만드는 일은 번거로우니까요.

 

Func를 쓸 경우

    public event Func<int> OnDeath;

펑크는 Action과 거의 똑같지만 반환값이 있는 메서드에 사용된다는 점이 유일하게 다릅니다. 때문에 여기서 OnDeath에 들어올 함수들은 void가 되서는 안되며 return값이 있어야합니다.

 

Event는 델리게이트를 이용해서 쓰는 것을 의미합니다.

 

이렇게 Delegate, event, Action, Func를 숙지했습니다. 다음 글에선 적의 공격을 구현해보겠습니다.