[Unity C#] 델리게이트 Delegate

윤재학·2022년 6월 17일

delegate란 함수에 대한 참조
하나의 델리게이트로 여러개의 함수를 접근하여 실행을 할수있습니다. 함수를 파라미터로 전달할 수 있고 여러개의 함수를 한번에 실행하는 체인기능, 어떠한 상황에 대한 이벤트를 발생 할수도 있습니다.
쉽게 말해 대리자(일을 대신해줄 비서를 만듬)
하지만 이 비서는 정해준 일 밖에 하지 못한다.


🔴 델리게이트의 기본

ex) delegate 리턴타입 델리게이트명(매개변수..)

delegate int Calculator(int numA, int numB);

int Add(int numA, int numB)
{ 
    return numA + numB;
}
int Sub(int numA, int numB)
{ 
    return numA - numB;
}

void Start()
{
    Calculator calculator = new Calculator(Add);
    
   Debug.Log(calculator(15,30));
}

델리게이트는 리턴타입과 매개변수가 모두 일치해야한다 ,
Add , Sub 함수의 형태와 같습니다. 참조변수와 같기 때문에 객체를 생성하고 , 괄호 안에는 참조할 함수를 넣는게 델리게이트의 기본 사용법 입니다.


🔴 델리게이트의 활용

delegate int Calculator(int numA, int numB);

int Add(int numA, int numB)
{ 
    return numA + numB;
}
int Sub(int numA, int numB)
{ 
    return numA - numB;
}

int Action(int numA, int numB, Calculator calculator)
{
    return calculator(numA, numB);
}

void Start()
{
    int Num = Action (10, 20, Add)
    Debug.Log(Num);
}

Action이라는 함수에 파라미터에 델리게이터를 통해 함수를 참조로 넘기게 된다!
Add로 함수의 참조 객체를 전달해 출력된 값은 더하기 연산이 나온다.


🔴 델리게이트 활용 2 : 델리게이트 체인

델리게이트체인은 하나의 델리게이트 안에 여러개의 함수를 연결하여 연쇄적으로 호출하는 방식이다.

+= 연산자를 이용해 인스턴스를 추가를 할수있고 ,
-= 연산자를 이용해 인스턴스를 삭제할 수있다.


delegate void Calculator(int numA, int numB);
Calculator calculator;
   
  void Add(int numA, int numB)
  { 
       Debug.Log(numA + numB);
  }
  void Sub(int numA, int numB)
  { 
       Debug.Log(numA - numB); 
  }
  void Mul(int numA, int numB)
   {
       Debug.Log(numA * numB); 
   }
  void Div(int numA, int numB)
   {
       Debug.Log(numA / numB);
   }
   
  void Start()
  {       
      calculator  = Add;
      calculator += Sub; // 추가
      calculator += Mul;
      calculator += Div;
      
      // calculator -= Sub; // 삭제
      
      
      calculator(5, 5);
   }
 

주석 처리를 해놓은 calculator -= Sub 를 삭제한다면 다음과 같은 결과가 나온다.


🔴 델리게이트 게임 사용 예시

플레이어가 몬스터와 충돌시 몬스터의 hp 바가 깎이고 , 점수가 오르고
플레이어의 버서커게이지가 올라간다고 가정을 하고 스크립트를 작성해보았다.
그중 몬스터의 Hp가 변할 때마다 생기는 다양한 처리들을 델리게이트로 묶어줄 수 있다.

1. delegate를 사용하는 몬스터 스크립트

public class Monster : MonoBehaviour
{
   public delegate void OnReduceHp();
   public OnReduceHp onReduceHp;
   
   public int hp = 100;
   public Slider hpSlider;
   
   public int Hp
       {
           get { return hp; }
           set { 
               hp = value;
               onReduceHp(); // 델리게이트를 사용한다.
               if(hp <= 0)
               {
                   Die();
               }
           }
       }
       
   public void Start()
   {
       onReduceHp += SetHpSlider;
       onReduceHp += GameManager.instance.ScoreUp;
   }
   
   public void Die()
   {
       Destroy(gameObject);
   }
   
   private void OnTriggerEnter(Collider other)
   {
       if(other.GetComponent<Player>() != null)
       {
           Hp -= 10;   // 플레이에게 충돌시 체력이 깎인다.
       }
   }
   private void Update() 
   {
        if(Input.GetKeyDown(KeyCode.Space)) 
        {
            Hp -= 5;
        }
   }
}       

start()에서 onReduceHp 델리게이트에 두가지 기능을 추가시켜놨다.
hp가 변할때마다 저 기능들이 수행되는 것.
1. hp 슬라이더 바
2. score 오르기!

일단은 스페이스바를 입력시 모든 몬스터가 데미지를 입도록 스크립트를 해준다.

2. 버서커 게이지를 가진 플레이어 스크립트

public class Player : MonoBehaviour
{
    public int berserkerGage = 0;

    public void BerserkerGageUp()
    {
        berserkerGage += 1;
    }
}

3. Score을 올려줄 게임 매니저 스크립트.

public class GameManager : MonoBehaviour
{
    public static GameManager instance;
    public int score=0;
    public int Score
    {
        get { return score; }
        set { 
            score = value;
            scoreText.text = score + "점";
        }
    }
    public void ScoreUp()
    {
        score += 10;
    }

    public Text scoreText;
    private void Awake()
    {
        if(instance == null)
        {
            instance = this;
        }
    }
}

4. 플레이어 근처에 몬스터가 있는지 체크를 위한 스크립트

그리고 특정상황 (여기서는 besekerzone안에 들어와있을 때)에서 델리게이트를 사용해
특정기능을 추가시켜주거나 제외시켜줄 수 있다.

public class BerserkerZone : MonoBehaviour
{

    private void OnTriggerEnter(Collider other)
    {
        if(other.GetComponent<Monster>() != null)
        {
            other.GetComponent<Monster>().onReduceHp += transform.parent.GetComponent<Player>().BerserkerGageUp; 
        } // onReduceHp 델리게이트에 간편하게 추가할수있다.
    }
    private void OnTriggerExit(Collider other)
    {
        if (other.GetComponent<Monster>() != null)
        {
            other.GetComponent<Monster>().onReduceHp -= transform.parent.GetComponent<Player>().BerserkerGageUp;
        }
    }
}

플레이어와 몬스터를 세팅 해주고 체크할 콜라이더를 달아준다.

스페이스바 입력시 플레이어의 콜라이더에 닿아있는 몬스터의 수에 따라 버서커 게이지가 상승한다.


이러한 예제를 통하여 캐릭터가 몬스터와 전투시 주변에 몬스터 수에 따라 게이지를 상승하는 시스템을 만들어
델리게이트 사용시 장점은 각각 클래스의 의존성(결합성)이 줄어들고 , 기능을 추가해주거나 수정해줄 경우 의존성이 낮게 간편하게 할수있다.


profile
노력하자 즐겁게 개발할수 있는 환경을 위해

0개의 댓글