본문 바로가기

유니티와 놀기

delegate 사용하기

  delegate는 특정 반환값과 인자를 받는 함수의 형을 선언해서 함수를 변수처럼 전달받을 수 있게한다.  다음은 예시를 위해 간단히 체력을 담당하는 스크립트를 만들었다. OnHealthSliderChange는 UI의 슬라이더가 움직일 때 마다 호출된다.

 

public class Health : MonoBehaviour
{
    public delegate void HealthCallback(float health);
    public HealthCallback healthCallback;

    public void HealthChange(float health)
    {
        Debug.Log("Method " + health);
    }

    void Start()
    {
        healthCallback += HealthChange;
        healthCallback += (float health) => { Debug.Log("Lamda " + health); };
    }

    public void OnHealthSliderChange(float value)
    {
        healthCallback.Invoke(value);
    }
}

 

 

public delegate void HealthCallback(float health);
public HealthCallback healthCallback;

 

 먼저 public delegate void DelegateName (float) 형식으로 원하는 delegate형을 만든다. 다음으로 DelegateName delegate 형식으로 변수를 만든다. 쉽게 말해 윗 줄은 클래스 내부에 클래스를 선언하는 것과 비슷하게 자료형을 만들고, 아래에서 그 자료형의 변수를 선언하는 식이다.

 

 만약 delegate를 private으로 선언할 경우 해당 delegate와 연관된 것들을 외부에서 접근할 수 없다. 만약 private delegate를 public으로 만들면 delegate형보다 delegate변수에 더 접근하기 쉬워져 컴파일 에러가 발생한다.

 

 

healthCallback += HealthChange;
healthCallback += (float health) => { Debug.Log("Lamda " + health); };

 

 이렇게 만든 delegate에는 = 또는 += 로 함수 또는 람다를 대입할 수 있다. C/C++의 함수 포인터에 함수를 넣는 것과 비슷하다. 다른점은 한 변수에 +=로 여러개의 함수를 동시에 집어넣을 수 있다는 점이다.

 

 

healthCallback.Invoke(value);

 

 대입된 함수를 실행할 때는 Invoke뒤에 파라미터를 전달해서 호출한다. 만약 여러 개의 함수를 넣었으면 모두 동일한 인자로 호출된다.

 

 

 

 delegate는 리스너 패턴을 만들 때 자주 사용된다. 만약 플레이어의 HP가 변화하고 그에 맞추어 HP게이지의 이미지를 수정해야할 때, HP게이지의 Update에서 플레이어의 HP를 계속 확인하고 갱신할 수 있다. 하지만 이는 HP가 변하지 않아도 불필요한 갱신을 하는 단점이 있다. 이 때 delegate를 사용해 HP게이지가 HP에게 콜백 함수를 넘겨줘 HP가 갱신될 때 호출되게 하면 해결할 수 있다.

 

public class BarType : MonoBehaviour
{
    public Health health;
    private Image image;

    public void Start()
    {
        image = GetComponent<Image>();
        health.healthCallback += OnHealthChange;
    }

    private void OnHealthChange(float health)
    {
        image.fillAmount = health;
    }
}

 

 HP게이지를 담당하는 BarType에서 위의 Health를 전달받고 health.healthCallback에 자신의 함수 OnHealthChange를 넣었다. 이 함수는 OnHealthSliderChange가 호출될 때 healthCallback.Invoke에서 호출될 것이다.

 

 

 이 방식을 사용하면 나중에 Health변수에 의존하는 오브젝트가 늘어나더라도 다른 부분의 수정 없이 해당 오브젝트가 콜백 함수를 더하기만 하면 된다는 장점이 있다.

'유니티와 놀기' 카테고리의 다른 글

간단한 단색 그래픽 만들기  (0) 2023.03.05
코루틴 뒤에 코루틴을 실행시키기  (0) 2022.11.10
체스말을 잡기  (0) 2022.11.04
체스말을 움직이기  (0) 2022.11.01