[Unity3D] 델리게이트 (Delegate)
델리게이트는 함수를 가리키는 변수라고 생각하면 쉽다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class DelegateTest : MonoBehaviour { delegate void NumDelegate(int Num); NumDelegate Del; void Start() { Del = FirstPlus; Del(5); Del = SecondPlus; Del(10); } void FirstPlus(int Num) { int Result = Num * Num; Debug.Log("FirstPlus : " + Result); } void SecondPlus(int Num) { int Result = Num * Num * Num; Debug.Log("SecondPlus : " + Result); } } | cs |
1. 델리게이트에 연결할 함수의 원형을 정의한다.
1 | delegate void NumDelegate(int Num); | cs |
Start() 함수 밑에 보면 2가지의 함수가 정의되어있다.
FirstPlus(인자)와 SecondPlus(인자)다.
2가지의 함수의 원형은 '자료형 함수이름(인자)' 이다.
즉, 밑의 2가지 함수를 델리게이트에 연결해서 사용하려면 델리게이트를 선언할 때
연결할 함수의 원형의 형태로 선언해야 한다.
델리게이트를 정의하는 방법은
delegate라는 키워드를 맨 앞에 적고 다음엔 자료형 그 다음에는 자신이 생각함 델리게이트의 함수이름을 정하고,
연결할 함수에 인자 값을 확인한 다음 똑같이 맞춰주면 된다.
delegate 자료형 함수이름(연결할 함수의 인자와 맞춤.)
2. 델리게이트 변수를 만든다.
델리게이트의 함수의 원형을 정의했으면 델리게이트 변수를 선언해야 한다.
1 | NumDelegate Del; | cs |
3. 델리게이트 변수에 함수를 연결.
1 2 3 4 5 6 7 8 | void Start() { Del = FirstPlus; Del(5); Del = SecondPlus; Del(10); } | cs |
연결 방법은 별거 없다.
변수 = 연결할 함수명.
이렇게 적어주면 되는데,
다만 조심해야 할 것은 '연결할 함수명'에 '()'를 붙이지 않는다.
델리게이트와 함수와의 연결이 끝났으면
델리게이트 변수를 함수를 사용하는 것처럼 사용하면 된다.
예제를 보면 사용하는 방법은 알겠는데 왜 쓰는거지?
그냥 함수명을 호출하면 되는거 아닌가? 라고 생각한다면
맞는 말이다. 다만, 이것은 예제이기 때문에 이렇게 사용한 것이지
적절한 사용법은 아니다.
그럼 언제 사용하는것이 좋을까?
예를 하나 들어보자
플레이어가 있고, 다수의 에너미가 있다고 하자.
다수의 에너미가 플레이어를 발견하고 공격하여 플레이어는 사망하였다.
플레이어가 사망하면 게속 공격할 필요가 없기 때문에 에너미는 공격을 멈추어야 한다.
즉, 플레이어가 죽었다는 사실을 알아야 한다.
그 사실을 알게하는 방법으로는 뭐가 있을 까?
방법은 많을 것이다.
보통으로 생각한다면 플레이어의 HP가 0이하로 떨어지는 순간
에너미들을 관리하는 리스트를 가지고와서 그 리스트를 차례대로 돌면서
플레이어가 죽었다는 사실을 알려주는 것이다.
하지만 에너미의 수가 아주 많다는 극단적인 상황이면 어떨까?
순차적인 호출 방법은 그리 효율적이지 않는 방법이 된다.
그렇기 때문에 델리게이트를 사용한다.
플레이어가 죽었을 때 엔진에게 '플레이어가 사망했다'라는 사실을 알려주어
이벤트를 발생시킨다. 이때 이 이벤트에 연결된 에너미에서 해당 동작을 수행하게 하면
순차적인 호출방식보다 속도면에서 효율적이게 될 것이다.
플레이어 스크립트
1. 델리게이트에 연결할 함수의 원형을 정의해준다.
2. 델리게이트 변수에 event키워드를 붙여 이벤트를 선언한다.
1 2 | public delegate void PlayerDieHandler(); public static event PlayerDieHandler OnPlayerDie; | cs |
이제 플레이어의 HP가 0이하가 되었을 때 OnPlayerDie()를 호출하면 된다.
그러면 OnPlayerDie에 연결된 함수가 대신 호출되게 된다.
1 2 | if (hp <= 0) OnPlayerDie(); | cs |
3. 델리게이트 OnPlayerDie에 함수를 연결한다.
2번의 OnplayerDie()가 호출되기 위해서는 델리게이트에 특정 함수가 연결되어야 한다.
그럼 연결은 언제 어디서 할것인가를 알아야 한다.
플레이어가 죽었을 때 에너미는 플레이어가 죽었다는 것을 알고 그에 맞게 행동해야 한다.
그에 맞게 행동하는 함수를 에너미 스크립트에 하나 만들자.
우리는 이 함수에 연결할 것이다.
그럼 연결하는 시점은 언제로 할 것인가?
1 2 | void OnEnable(); void OnDisable(); | cs |
※ 두 함수는 유니티에서 기본적으로 제공하는 함수다.
OnEnable() 함수가 호출되는 시점에서 델리게이트를 연결할 것이다.
OnEnable() 함수와 OnDisable()함수는 각각 스크립트가 활성화 되었을 때, 스크립트가 비활성화 되었을 때 호출된다.
연결하는 방법은 예제와는 다르게 이퀄 앞에다가 +을 붙여야 한다.
예제 - 델리게이트 변수 = 연결할 함수이름.
본문 - 이벤트가 선언된 클래스명.델리게이트 변수 += 연결할 함수이름.
반대로 에너미가 죽었을 경우 연결을 해제 시켜줘야할 필요가 있다.
이때에는 이벤트가 선언된 클래스명.델리게이트 변수 -= 연결된 함수이름.
으로 하면 된다.
그냥 말로만 듣는것보다 한 번 보는게 좋다고 생각한다.
Enemy Script
1 2 3 4 5 6 7 | void OnEnable() { PlayerCtrl.OnPlayerDie += this.OnPlayerDie; } void OnDisable() { PlayerCtrl.OnPlayerDie -= this.OnPlayerDie; } void OnPlayerDie() { // 추적 및 공격 중단. } | cs |
'Unity3D > Tip' 카테고리의 다른 글
[Unity3D] EventSystem (1) | 2017.05.03 |
---|---|
[Unity3D] 유니티 스플래시 스크린(로고 삽입) (0) | 2017.05.02 |
[Unity3D] 메카님으로 설정된 3D모델 최적화. (0) | 2017.04.29 |
[Unity3D] Shadow - 그림자 생성. (0) | 2017.04.27 |
[Unity3D] Trail Renderer - 궤적 (0) | 2017.04.27 |