본문 바로가기
Unity 게임 개발

C# Unity Delegate 설명 및 사용법

by daisy0461 2021. 5. 9.

이번에는 Delegate에 관해서 공부를 해보려고 합니다.

대학교 졸업작품을 하는 도중에 친구가 Delegate와 관련하여 질문을 하였고

저는 잉?? 그게 뭐지라는 생각에 이번 공부를 진행하게 되었습니다.

 

Delegate란 함수를 넣어 변수처럼 사용할 수 있는 형태입니다.

 

밑에 예시를 보여드리겠습니다. 

현재 위 사진과 같이 Cube라는 Object에 Delegate_Ex라는 C# Script를 추가를 하였습니다.

 

Delegate_Ex는 다음과 같습니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Delegate_Ex : MonoBehaviour
{
    delegate void MyDelegate();
    MyDelegate myDelegate;
    // Start is called before the first frame update
    void Start()
    {
        myDelegate = PrintName;
        myDelegate();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void PrintName(){
        Debug.Log("JJ의 코딩 실력 쌓기");
    }
}

 

그리고 실행을 해본다면 

콘솔 창에 Log가 찍히는 것을 확인할 수 있습니다.

 

이처럼 함수를 받아와서 변수처럼 사용하는 방법이 Delegate입니다.

그리고 Delegate에는 하나의 함수 뿐만 아니라 여러가지를 추가해서 사용할 수 있습니다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Delegate_Ex : MonoBehaviour
{
    delegate void MyDelegate();
    MyDelegate myDelegate;
    // Start is called before the first frame update
    void Start()
    {
        myDelegate += PrintName;
        myDelegate += PrintScore;
        myDelegate += PrintThis;
        myDelegate();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void PrintName(){
        Debug.Log("JJ의 코딩 실력 쌓기");
    }

    private void PrintScore(){
        Debug.Log("100점!!");
    }

    private void PrintThis(){
        Debug.Log(this.name);
    }
}

 

이와 같이 myDelegate에 +=을 활용하여 추가를 할 수 있습니다. 이것을 실행시키면

들어갔던 순서대로 실행이 되는 것 또한 확인을 할 수 있습니다.

추가할 때는 +=과 마찬가지로 뺄 때는 -=을 활용하시면 빼실 수 있습니다.

 

이 Delegate에서 주의할 점은

Delegate를 처음 선언 할 때 return type과 파라미터의 수와 type이 일치해야한다는 점입니다.

현재 Delegate는 방금 전과 동일하게 void형에 파라미터는 없습니다.

그리고 지금 PrintScore를 보았을 때 int형 파라미터를 하나 받고 있습니다.

이 PrintScore를 myDelegate에 추가를 하려고 하면 붉은 줄이 그이며 오류가 생기는 것을 확인 가능합니다.

 

이처럼 return type과 파라미터를 일치시켜야 Delegate에 넣을 수 있습니다.

 

이러한 Delegate를 왜 사용하나??

그냥 함수 불러와서 하면 괜찮지 않나 라는 생각을 할 수 있습니다.

하지만 Delegate를 사용하면 원하는 함수만 묶어서 가능해서 추상화하기 좋고 함수를 분할하기가 좋습니다.

아래는 간단하게 float의 값만 변화시켰지만 복잡한 기능이 다양하게 들어가게 된다면 어디서 에러가 발생하는지 찾기 힘듭니다.

그때 함수가 따로 분할되어있어서 각각 테스트가 가능하다면 찾기 편해질 수 있습니다.

 

Delegate를 사용하는 간단한 예시로는 캐릭터가 

공격력과 스피드가 함께 증가하는 경우를 쉽게 코딩할 수 있습니다. 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Delegate_Ex : MonoBehaviour
{
    delegate void MyDelegate();
    MyDelegate myDelegate;

    public float attack = 10.0f;
    public float speed = 10.0f;
    // Start is called before the first frame update
    void Start()
    {
        myDelegate += SpeedUp;
        myDelegate += AttackUp;
        myDelegate += PrintAttackSpeed;
    }

    // Update is called once per frame
    void Update()
    {
        myDelegate();
    }

    private void SpeedUp(){
        speed++;
    }

    private void AttackUp(){
        attack++;
    }

    private void PrintAttackSpeed(){
        Debug.Log("Attack: " + attack);
        Debug.Log("Speed: " + speed);
    }

}

 

위와 같이 코딩을 한 후에 실행을 시켜본다면 Update에 의해 프레임 당 attack과 speed가 증가하는 것을

확인할 수 있습니다.