개발블로그
[유니티 C#] 함수 대리자. 델리게이트 (Delegate), 이벤트(event) 본문
💪 GOAL
함수 대리자 델리게이트(delegate)를 응용 예제를 만들고 이해 한다.
🔶 델리게이트(대리자, Delegate)
- 델리게이트(Delegate)는 어떤 기능을 추가해줬을 때, 델리게이트가 그 목록을 대신 실행시켜주는 대리자이다.
함수에 대한 참조라고도 한다. 하나의 델리게이트로 여러 함수들에 접근해 실행할 수 있으며,
델리게이트를 이용해 함수를 매개변수로 전달 할 수 있고, 여러 함수를 한꺼번에 실행하는 체인 기능이 있다.
그리고 어떠한 상황에 도달 했을 때 이벤트를 발생 시키는 델리게이트 이벤트도 제공 된다.
함수의 포인터처럼 사용할 수 있는 기능으로, 함수 타입의 참조형 변수를 통해 전달 받은 객체 내/외부의 함수를 실행할 수 있으며 이를 통해 디커플링/일반화를 달성할 수 있다.
델리게이트를 사용하지 않으면 클래스 이름에 의존적이게 된다.
즉, 다른 클래스와 연결해서 작업해야하는 경우 새로운 라인을 추가하거나
코드상에서 연결하는 클래스 이름을 바꾸는 등 작업을 해줘야하는데
델리게이트를 사용하면 연결할 클래스에 상관없이 동작할 수 있어서 추가 작업이 필요 없게 된다.
1. 델리게이트 선언
싱글턴 클래스로 사용하기 위한 PowerupManager 클래스의 델리게이트 선언부이다.
public class PowerupManager : MonoBehaviour
{
public delegate void PowerupChangedHandler(PowerupType newType,PowerupType oldType);
}
위의 코드에서 PowerupChangeHandler 델리게이트를 선언했다.
델리게이트의 선언은 그림1 과 같다.
1. public : 접근제한자로 이 델리게이트 형식은 외부에서 접근 가능함을 나타낸다.
2. delegate : 대리자 선언
3. void : 리턴형. 반환 값이 없음을 뜻한다.
4. PowerupChangeHandler : 델리게이트 형식의 이름을 나타낸다.
5. (매개 변수) : 매개변수를 받음을 나타낸다.
2. 델리게이트 사용
이렇게 선언한 델리게이트 형식은 아래와 같이 변수를 생성하여 사용할 수 있다.
public enum PowerupType
{
None,
Weak,
Strong,
}
public class PowerupManager : MonoBehaviour
{
public delegate void PowerupChangedHandler(PowerupType newType, PowerupType oldType);
public static event PowerupChangedHandler PowerupChanged;
public PowerupType currentType;
public void SetType(PowerupType t, bool toggle = true)
{
PowerupType oldValue = currentType;
PowerupType newValue = t;
if (oldValue == newValue && toggle)
{
newValue = PowerupType.None;
}
currentType = newValue;
if (oldValue != newValue && PowerupChanged != null)
PowerupChanged(newValue, oldValue);
}
}
public delegate void PowerupChangedHandler(PowerupType newType, PowerupType oldType);
public static event PowerupChangedHandler PowerupChanged;
public void SetType(PowerupType t, bool toggle = true)
{
if (oldValue != newValue && PowerupChanged != null)
PowerupChanged(newValue, oldValue);
}
* 중요 포인트
1. PowerupChangedHandler
: 선언한 PowerupChangedHandler 타입의 변수임을 나타낸다.
event로 선언한 델리게이트 변수는 변수를 선언한 클래스에서만 실행된다.
접근제한자와 비슷한 느낌으로 event를 붙이면 외부에서 델리게이트 체인을 거는 것은 가능하지만 실행은 불가능하다.
2. PowerupChanged
: 변수명을 나타낸다.
3. PowerupChanged(newValue, oldValue)
: PowerupChanged 델리게이트에 newValue, oldValue 두개의 변수를 넣어서 실행 한다.
✔ event 키워드
이벤트 키워드는 해당 이벤트가 선언된 클래스/구조체에서만 호출할 수 있게 하는 멀티캐스트 대리자를 만드는 키워드이다.
public event PowerupChangedHandler PowerupChanged;
: public 접근제한자를 통해 선언되어 외부에 공개되 있어 -=, +=, = 등을 통해 델리게이트 체인에 등록/삭제/할당 하거나 내용을 볼수 있다.
하지만 외부 클래스/구조체에서 PowerupManager.PowerupChanged() 같은 형태로 실행할 수 없다.
public PowerupChangedHandler PowerupChanged;
: 공개된 PowerupChangedHandler 대리자 타입의 PowerupChanged 변수를 선언한다.
이 변수는 외부 클래스에서 PowerupManager.PowerupChanged() 같은 형태로 실행할 수 있다.
다른 예제 코드를 보자.
public delegate int delegateCalculation(string x, int y);
delegateCalculation deCal;
void Start()
{
deCal = myDeCal;
}
int myDeCal(string x, int y)
{
Debug.Log("string : " + x + " , int : " + y);
return 10;
}
1. delegateCalculation
: 선언한 delegateCalculation 타입의 변수임을 나타낸다.
2. deCal
: 변수명을 나타낸다.
3. deCal = myDeCal
: 선언한 대리자 변수 deCal에 시그니처가 동일한 함수인 myDecal을 = 를 통해 할당한다.
+=, -= 를 사용하면 델리게이트 체인을 사용할 수 있다.
3. 델리게이트 체인
델리게이트로 선언된 변수는 단순 할당이 아닌 +=, -= 등을 통해 함수의 등록/삭제가 가능하다.
이를 통해 다수의 함수를 하나의 대리자에 등록하여 한번에 실행하거나
하나의 함수를 여러번 등록하여 여러번 실행하거나 하는 등의 동작도 수행가능하다.
델리게이트 체인도 선언된 델리게이트에 등록하기 위해서는 동일한 시그니처의 함수여야 한다.
public delegate int delegateCalculation(string x, int y);
delegateCalculation deCal;
void Start()
{
deCal += myDeCal;
deCal += yourDeCal;
Debug.Log("result : " + deCal("12", 34));
}
int myDeCal(string x, int y)
{
Debug.Log("string : " + x + " , int : " + y);
return 10;
}
int YourDeCal(string z, int o)
{
Debug.Log("Del your Cal string : " + z + ", int : " + o);
return o + 10;
}
deCal에 동일한 시그니처를 가진 함수 myDecal과 YourDeCal을 델리게이트 체인으로 추가하고 대리자를 실행하면
대리자에 델리게이트 체인으로 등록한 모든 함수를 순서대로 실행한다.
참고로 리턴값이 있는 델리게이트(Func) 을 델리게이트 체인으로 실행하면 마지막 함수의 결과 값을 리턴한다.
* 공부하는 단계입니다. 잘못된 부분이 있다면 피드백 부탁드립니다 ☺
* e-mail : heehee970@naver.com
'Unity > 스크립팅' 카테고리의 다른 글
[유니티 C#] Action 과 Func (0) | 2021.09.04 |
---|---|
[유니티 C#] 유니티의 시간 마법사 Time.timeScale, 그리고 Time.unscaledTime (0) | 2021.08.11 |
[유니티 C#] Time.deltaTime, Application.targetFrameRate을 통한 프레임 제어 (0) | 2021.08.04 |
객체 지향 프로그래밍(OOP)에서의 클래스 개요. 변수와 프로퍼티의 차이 (0) | 2021.08.02 |
[유니티 C#] Destroy와 DestroyImmediate 의 차이점 (0) | 2021.07.27 |