공부용으로 작성되는 페이지입니다. 틀린 부분이나 환경에 따라 오류가 발생할 수 있습니다.
1. Delegate 란?
'대리자' 라는 의미를 가지고 있으며 함수의 주소값을 가지고 대신 호출한다. Class, Array, Interface와 같은 참조형 타입이다.
메서드를 매개변수로 전달하거나, 런타임에 호출될 메서드를 동적으로 연결할 때 유용하며 매개변수로 가져오는 덕분에 결합도를 낮출 수 있어 C언어의 포인터와 유사하다.
델리게이트는 다른 함수를 특정 함수값으로 반환하고싶거나 매개변수로 가져오고 싶을때, 혹은 Call back이 필요할 때
사용한다. 그리고 시그니처만 동일하다면 여러개의 함수를 참조할 수 있다.
2. Delegate 사용하기: 정의와 선언
Delegate를 선언할 때는 호출할 함수의 시그니처(형식)을 확인하도록한다.
#델리게이트선언 방법
delegate 반환형식 델리게이트명(매개변수..);
#example
delegate int TestInt(int x, int y);
delegate void TestDelegate();
#필요에 따라 접근제한자를 함께 작성한다
#델리게이트 선언과 사용법
#ex1
public delegate void TestDelegate(); #델리게이트 정의
public TestDelegate testDelegate; #델리게이트 객체(변수) 선언
private void Start()
{
testDelegate = LogPrint;
testDelegate();
}
private void LogPrint() #참조 메소드
{
Debug.Log("Testwrite"); #테스트용 Log 출력 함수
}
#ex2
public delegate int MathDelegate(int x, int y); //델리게이트 정의
MathDelegate mathDelegate = new MathDelegate(divid); //델리게이트 객체 선언
private void Start()
{
int res = mathDelegate(120, 2);
Debug.Log(res);
}
static int divid(int x, int y) { return x / y; }
3. Delegate Chain : 여러 함수 참조하기
1에서 언급했듯이 Delegate는 여러 함수를 동시에 참조할 수 있다. 이것을 Delegate Chain이라고 한다.
주로 +=를 사용해서 참조를 추가한다. 반대로 -=를 사용해서 참조를 해제할 수 있다.
#예제
#레벨업
int _Mylevel = 4; #현 레벨
int _MyHP = 30; #fullHP는 100
int _Myexp = 90; #레벨업하면 exp는 0으로 초기화된다.
#delegate선언 및 객체
public delegate void LevelupDelegate(int level, int HP, int exp);
LevelupDelegate levelupDelegate;
void Start()
{
#delegate chain, 여러 함수를 참조한다
levelupDelegate = LVup;
levelupDelegate += HPfull;
levelupDelegate += expback;
levelupDelegate.Invoke(1, 100, 0);
}
#참조할 함수들
void LVup(int level, int HP, int exp)
{
_Mylevel = _Mylevel + level;
Debug.Log("Level : " + _Mylevel);
}
void HPfull(int level, int HP, int exp)
{
_MyHP = HP;
Debug.Log("HP : " + _MyHP);
}
void expback(int level, int HP, int exp)
{
_Myexp = 0;
Debug.Log("exp : " + _Myexp);
}
* 사실 이 예시의 상황(레벨업)은 하나의 함수로 충분히 가능하기때문에 델리게이트 체인을 써야할 상황은 아니다. 어디까지나 이런식으로 여러 함수를 동시에 참조할 수 있다는 것에 주목하자.
4. Event와 EventHandler
- Event
Event는 조건을 만족 했을 때 객체의 상태 변화나 사건이 자동으로 실행되도록 하는 기능이다.
event 키워드와 함께 쓰이며, 외부에서 호출할 수 없다. 이런 특성상 안정적인 프로그래밍이 가능하다.
이벤트 여러 구독자들이 있을 때 사용하는 것이 좋다.
즉, 한 사건이 발생했을 때 여러 구독자들이 그 이벤트에 영향을 받아야 할 때 쓰는 것이다.
#ex
#모든 적들에게 플레이어의 위치를 전달하는 이벤트
#1. 이벤트를 관리하는 이벤트 매니저 - delegate event를 작성
public delegate void PlayerFindEvent(Vector3 playerposition);
public static event PlayerFindEvent OnPlayerFind;
public static void KnowAllEnemy(Vector3 playerposition)
{
OnPlayerFind.Invoke(playerposition);
}
#2. 구독자(Enemy)
private bool FindPlayer = false;
private Vector3 lastknownPlayerPosition;
void Start()
{
LinkInfo(); #보통 생성되거나 소멸할 때 이벤트 구독과 해지를 해주는게 좋다.
private void Update()
{
if(!FindPlayer)
{
DetectPlayer();
}
else
{
ChasePlayer();
}
}
private void DetectPlayer()
{
Collider[] hitColliders = Physics.OverlapSphere(transform.position, 5f); // 5m 범위 탐색
foreach (Collider col in hitColliders)
{
if (col.CompareTag("Player")) #플레이어가 범위 안에 있으면
{
Debug.Log(gameObject.name + "이(가) 플레이어를 발견했다!");
FindPlayer = true;
lastknownPlayerPosition = col.transform.position;
#모든 적에게 플레이어 발견 알림
EventManger.FindPlayerEvent(lastknownPlayerPosition);
break;
}
else { Debug.Log("순찰중입니다..."); }
}
}
private void LinkInfo() #이벤트 구독용 메소드
{
Debug.Log("아군과 정보를 링크합니다.");
EventManger.OnPlayerFind += OnPlayerDetected; //시그니처가 동일하므로 체인해줄 수 있다.
}
private void OnPlayerDetected(Vector3 playerPosition)
{
if(!FindPlayer) #플레이어를 찾지 못 한 Enemy들의 경우에만
{
Debug.Log("정보를 제공받았습니다");
FindPlayer = true;
lastknownPlayerPosition = playerPosition;
}
}
private void ChasePlayer() #이 부분은 따로 작성하지 않았다.
{
if(FindPlayer == true)
{
Debug.Log("추격내용");
}
}
- EventHandler
EventHandler는 Unity system내에 이미 델리게이트로 정의가 되어 있기 때문에 따로 델리게이트를 선언하지 않고 그대로 사용한다.
#EventHandler의 구성
public delegate void EventhHandler(object sender, EventArgs e);
object Sender : 이벤트를 실행시키는 객체
EventArgs : 이벤트 실행 시 전달하고 싶은 정보에 대한 매개변수. 상속으로 사용한다.
public event EventHandler eventhandler; #using System;이 작성되어있다면, 이렇게 바로 사용할 수있다.
* 이벤트 핸들러의 경우 예시 코드를 작성할만큼 이해하지 못 했으므로 다시 공부 후 작성한다.
5. Lambda
Lambda식은 즉각적으로 사용되어야하거나 이름이 없는 함수를 편리하게 사용할 수 있게 해주는 익명 함수이다.
즉 별도의 메소드 선언 없이 간결하게 작성할 수 있다. 다만 익명 함수인만큼 디버깅이 어려우므로 주의해서 사용해야한다.
Delegate = (a, b) => a + b;
람다식은 =>으로 표현된다.
#LambdaExample
delegate int TestDelegate(int a,int b);
private void Start()
{
TestDelegate testDelegate;
testDelegate = (int a, int b) => a+ b; //람다식
int res = testDelegate(3, 5);
Debug.Log(res);
}
참고 자료
C# event 사용(delegate)
1. event 개념 이벤트(event)의 용어 정의는 "사건"을 의미합니다. 프로그래밍에서 event도 비슷한 개념으로 "어떠한 조건을 만족하는 사건"이 발생했을 때, 자동으로 실행을 할 수 있도록 하는 것 입
woojoolog.tistory.com
C# 프로그래밍의 기초 : Lambda (람다식)
람다식은 C#에서 강력하고 유연한 프로그래밍을 가능하게 하는 중요한 기능 중 하나입니다. 이는 익명 함수를 간결하게 표현할 수 있는 방법을 제공하며, 매개변수 목록, => 연산자, 그리고 식 또
unialgames.tistory.com
c# delegate, event 사용법 및 사용예제
1. delegate란 delegate는 메서드 대리자입니다. delegate로 메서드 대리자를 선언해주고 원하는 메서드를 참조시킬수 있습니다. 쉽게말하면 함수를 보관하는 통을 만들고(대리자선언) 그 통안에 함수
frozenpond.tistory.com
'유니티 > C#' 카테고리의 다른 글
[C#] SOLID 원칙 : 개방 폐쇄 원칙 - OCP (Open Closed Principle) (0) | 2025.03.20 |
---|---|
[C#] Delegate : Action, Func (0) | 2025.03.16 |
[C#] SOLID 원칙 : 단일 책임 원칙(SRP) (0) | 2025.03.06 |