Unity - Message


Unity Message System이란?

최근 작업하고 있는 유니티 스크립트에서 Message로 send하는 형태의 문이 많이 나와서 개념과 사용법이 헷갈려 다시 정리하게 되었다.

우선 유니티의 공식문서이다.

이름으로 메소드를 호출하다. SendMessage

Uity 런타임 시스템에서는 Unity 자체의 캐시 시스템을 이용하여 컴포넌트의 메소드를 문자열로 찾아 호출해주는 기능을 가지고 있다.

그 중 하나는 GameObjectComponent 클래스에 존재하는 SendMessage라는 메소드이다.

void OnEnable(){
  SendMessage("DoSomething");
}

void DoSomething(){
  Debug.Log("Do something!");
}

OnEnable에서 해당 컴포넌트의 DoSomething이라는 메소드를 찾아 호출하는 SendMessage 메소드를 호출하고, DoSomething 메소드에서 로그가 출력된다.

Unity에서 이런식으로 메시징 방식을 이용하는 대표적인 사례는 컴포넌트 스크립팅을 할 때 항상 볼 수 있는 Start, Update 등 MonoBehaviour의 여러 메시지 콜백들이다.

메시지 콜백들을 통해 스크립트 컴포넌트는 여러 상태를 알 수 있다.

메시징 방식의 장단점

장점

  1. 타입에 상관 없이 문자열 하나로 메소드 호출이 가능하다(Typeless call)

단점

  1. 빈번한 호출은 피한다.

문자열 탐색에 대한 비용이 있으니 매 프레임마다 호출하거나 빈번한 사용이 일어날 때에는 사용을 지양해야 한다.

  1. 생성시에 부하가 발생한다.

컴포넌트 생성 타이밍에 C# Reflection 기능을 이용해 메소드 데이터를 생성하는데, 이때 부하가 발생한다.

퍼포먼스가 필요한 게임에서는 GameObejct의 생성은 되도록 피하고, 모든 오브젝트를 가장 처음에 로드 후 재활용해서 사용한다.

  1. OOP를 망친다.

접근 제한자에 상관없이 호출해주기 때문에 객체 캡슐화에 안좋은 영향을 미친다. OOP에서는 접근 제한자를 통해 외부에 노출시킬 메소드, 안에서 숨겨야 할 메소드를 설정한다.

하지만 Unity 메시징 방식은 접근 제한자를 무시하기 떄문에 프로그래머에게 모호한 선택을 요구한다.

언제 사용하나?

생성 및 초기화 같이 시작과 끝에서 호출되거나 정말 쓸 수 밖에 없는 경우(애니메이션 이벤트)에 사용한다. 혹은 성능이 필요 없는 UI에 쓰기도 한다.

Unity MessagingC# Delegate
비교적 느림비교적 빠름
한번에 메소드 호출이 가능직접 메소드를 이어주고 호출해줘야 함

매 프레임마다 호출되거나 자주 호출이 되는 경우에는 C# Delegate 문법을, 성능이 필요없는 부분(생성, 파괴)에서 호출할 때는 SendMessage를 사용하면 된다.