본문 바로가기
Development/멋쟁이사자처럼 게임개발 부트캠프

[멋쟁이사자처럼 Unity 게임 부트캠프 4기] 11일차 - 델리게이트 & 이벤트

by jjeondeuk1008 2025. 3. 16.
반응형

 


 

11일차 ! 곧 2주를 향해 다가간다.

 

이제 오늘을 마지막으로 C#에 대해 배우고,

내일부터는 유니티로 넘어간다.

 

오늘을 포함해 지금까지 배웠던 것을

이제 게임 만들면서 활용할 것이다. 벌써부터 기대중

 

그럼 마지막 C# 콘솔 공부 화이띵!!!

 

 

 


 

1. 델리게이트 (Delegate)

 

델리게이트(Delegate)는 메시지 출력을 위한 메서드 참조이다.

string 매개변수를 받고 반환값이 없는 void 메서드를 참조할 수 있는 타입이다.

class Program
{
    delegate void MessageHandler(string message);

    //델리게이트에 연결할 메서드
    //메서드 형과 타입 이런 게 일치해야 받아줌
    static void DisplayMessage(string message)
    {
        Console.WriteLine($"메시지: {message}");
    }

    static void DisplayUpperMessage(string message)
    {
        Console.WriteLine($"대문자 메시지: {message.ToUpper()}");
    }

    static void Main(string[] args)
    {
        Console.WriteLine("== 간단한 델리게이트와 이벤트 예제 ===");

        //1. 델리게이트 사용해보기
        Console.WriteLine("델리게이트1");

        //델리게이트 변수 선어 및 메서드 연결
        //DisplayMessage 메서드를 messageHandler 변수에 할당
        MessageHandler messageHandler = DisplayMessage;

        //델리게이트 호출 - 연결된 메서드가 실행됨
        messageHandler("안녕하세요");

        //델리게이트 다른 메서드 추가(멀티캐스트 델리게이트)
        //+= 연산자로 메서드 추가
        messageHandler += DisplayUpperMessage;

        //여러 메서드가 연결된 델리게이트 호출
        //등록된 모든 메서드가 순사대로 호출됨
        Console.WriteLine("여러 메서드 호출: ");
        messageHandler("Hello ");
    }
}

 

 

호출 순서를 알아보자.

 

1번

Main에서 시작되는 것이니 기존 호출인 문자열을 출력하고,

 

2번

델리게이트 변수 선언 및 메서드에 연결한 것이 다음 실행이다.

변수에 displayMessage 메서드를 가져온다.

displayMessage는 (메시지: {message})이다.

 

3번

델리게이트를 호출한다.

(메시지: {message}) 여기에서 message가 "안녕하세요"로 적용되어

 

이 값이 4번으로 향해

메시지: 안녕하세요

이렇게 호출 된다.

 

5번

연산자로 메서드를 추가한다.

연결된 메서드가

 

6번으로 이동해

문자열을 하나 호출하고,

messageHandler("Hello ")

 

코드가 7번으로 이동해

메시지: Hello

이렇게 호출한다.

 

Hello 값8번으로 이동해

ToUpper()를 통해 대문자로 변환이 되어

대문자 메시지: HELLO

마지막인 호출을 하는 것이다.

 

 

 


 

2. 이벤트

 

이벤트는 특정 상황이 발생했을 때 알림을 보내는 것이다.

 

이벤트헨들러(EventHandler)는 C#에서 제공하는 기본 델리게이트 타입이다.

이벤트가 발생했을 때 실행될 메서드인 것이다.

 

 

아래의 예제를 통해 코드 실행 순서에 따라 자세하게 더욱 설명하겠다.

 

Charater 클래스에서

Name과 Health로 캐릭터의 이름과 체력을 저장하는 변수이다.

get만 수정이 가능하며, private set은 외부에서 수정할 수 없게 하였다.

 

아직 실행은 되지 않는다.

 

Program 클래스에서

Hero_OnDamaged 메서드 (이벤트 헨들러)가 정의된다.

 

아직 실행이 되지 않는다.

 

우선 Main 함수에서 실행을 시작하게 된다.

캐릭터 생성으로 Character 객체인 hero를 생성한다. (이름: "용사", 체력: 100)

 

+= 연산자를 통해

hero의 OnDamaged 이벤트에 Hero_OnDamaged 메서드를 등록한다.

"이벤트 알림: 용사가 데미지를 입었습니다!" 출력한다.

 

-= 연산자를 통해

.Hero_OnDamaged 메서드 이벤트 구독을 취소한다.

그래서 이벤트가 발생해도 호출되지 않는다.

//게임 캐릭터 클래스
class Character
{
    //속성
    public string Name { get; private set; }
    public int Health { get; private set; }

    //이벤트 정의 - 캐릭터가 데미지를 입었을 때 발생
    //EventHandler는 C#에서 제공하는 기본 델리게이트 타입
    //이벤트는 외부에서 직접 호출할 수 없고, +=와 -= 연산자로만 접근 가능
    public event EventHandler OnDamaged;

    //생성자
    public Character(string name, int health)
    {
        Name = name;
        Health = health;
    }

    //데미지를 입는 메서드
    public void TakeDamage(int amount)
    {
        Health -= amount;
        Console.WriteLine($"{Name}{amount}의 데미지를 입었습니다. 남은체력: {Health}");

        //이벤트 발생 (구독자가 있는 경우에만)
        //?. 연산자 OnDamaged가 null이 아닐 때만 invoke 메서드 호출
        //EventArgs.Empty는 추가 데이터가 없을 때 사용하는 빈 이벤트 인자
        OnDamaged?.Invoke(this, EventArgs.Empty);
    }
}

class Program
{
    //이벤트 핸들러 메서드
    //EventHandler 델리게이트와 일치하는 시그니처를 가져야함
    //sender: 이벤트를 발생시킨 객체 (여기서는 Character 객체)
    //e: 이벤트와 관련된 추가 데이터(여기서는 사용하지 않음)
    static void Hero_OnDamaged(object sender, EventArgs e)
    {
        //sender를 character 타입으로 형변환
        Character character = (Character)sender;

        Console.WriteLine($"이벤트 알림: {character.Name}가 데미지를 입었습니다! "
            + $"현재 체력: {character.Health}");
    }

    static void Main(string[] args)
    {
        //캐릭터 생성
        Character hero = new Character("용사", 100);

        //이벤트 구독 +=
        //이벤트가 발생했을 때 실행될 메서드 등록
        hero.OnDamaged += Hero_OnDamaged;

        //데미지 입히기
        //TakeDamage 메서드 내에서 OnDamaged 이벤트가 발생함
        hero.TakeDamage(30);

        //이벤트 구독 취소 -=
        //더이상 이벤트 발생시 메서드가 호출되지 않음
        hero.OnDamaged -= Hero_OnDamaged;
        Console.WriteLine("이벤트 구독 취소 ");
        hero.TakeDamage(20);

    }
}

 

 

 

 


 

 

드디어 마지막 콘솔 공부가 끝이났다.

 

11일이라는 숫자만 봐서는 짧게 느껴지지만,

대략 2주에 걸쳐 배웠다.

 

 

고생했다 . . . . . .

 

다음에 있을 유니티도 힘내ㅈ ㅏ.. . . .


목차