버튼을 클릭시에 UnityEvent를 기본 모델로 하여서 애니메이션이 동작하도록 하는 기본 클래스를 Animated Button이라고 만들때, 이때에 UnityEvent를 상속한 ButtonClickedEvent 를 AnimatedButton 클래스 내부에 만들고, 해당 ButtonClickEvent를 사용한 로직을 구상할 구 있다.
이때에 내부 기능을 하는 핵심적인 부분을 첨부하자면,
[Serializable]
public class ButtonClickedEvent : UnityEvent
{
}
public bool interactable = true;
[SerializeField]
private ButtonClickedEvent m_onClick = new ButtonClickedEvent();
private Animator animator;
private bool blockInput;
public ButtonClickedEvent onClick
{
get { return m_onClick; }
set { m_onClick = value; }
}
protected override void Start()
{
base.Start();
animator = GetComponent<Animator>();
}
/// <summary>
/// Called when there is a click/touch over the button.
/// </summary>
/// <param name="eventData">The data associated to the pointer event.</param>
public virtual void OnPointerClick(PointerEventData eventData)
{
if (eventData.button != PointerEventData.InputButton.Left || !interactable)
{
return;
}
if (!blockInput)
{
blockInput = true;
Press();
StartCoroutine(BlockInputTemporarily());
}
}
위와 같은데, 이때에
[Serializable]
public class ButtonClickedEvent : UnityEvent
{
}
에 대해서 얘기를 해보려 한다.
여기서 사용한 [Serializable] 을 왜 사용하는지, 해당 어트리뷰트를 사용하면 어떤 결과가 나타나는지에 대해서 알아보자.
일단 위와 같은 어트리뷰트에 대한 설명을 chatGPT 를 통해 검색해보면,
`[Serializable]` 어트리뷰트는 해당 클래스 또는 구조체를 직렬화 가능하다고 표시하는 역할을 합니다. 직렬화(serialization)는 객체의 상태를 저장하거나 전송하기 위해 데이터를 바이트 스트림으로 변환하는 과정을 말합니다.
`ButtonClickedEvent` 클래스는 Unity의 `UnityEvent`를 상속받아 사용자가 버튼을 클릭했을 때 호출될 이벤트를 나타냅니다. 그리고 `[Serializable]` 어트리뷰트가 클래스 위에 사용되면 이 클래스의 인스턴스는 인스펙터 창에서 노출되어 편리하게 사용자가 설정할 수 있게 됩니다.
Unity의 `UnityEvent`는 Inspector 창에서 이벤트를 설정할 수 있도록 직렬화된 클래스입니다. 그러나 직렬화된 클래스를 사용자 정의 클래스에 적용하려면 `[Serializable]` 어트리뷰트를 명시적으로 사용해야 합니다.
이 코드에서는 `AnimatedButton` 클래스의 `m_onClick` 필드가 `ButtonClickedEvent` 타입이고 `[Serializable]` 어트리뷰트가 이 타입 위에 사용되어 해당 이벤트가 인스펙터 창에서 설정 가능하도록 하고 있습니다. 사용자는 Unity Editor에서 이 이벤트에 대한 처리 로직을 추가할 수 있습니다.
위와 같은 답을 얻을 수 있다.
이때에 가장 핵심인 부분은 "이 클래스의 인스턴스는 인스펙터 창에서 노출되어 편리하게 사용자가 설정할 수 있게 됩니다" 라는 부분이다.
위에서 사용하는 [Serializable] 어트리뷰트를 통해서 인스펙터 창에서 확인할 수 있고 해당 인스펙터 창에 표시된 부분에서 사용자가 ButtonClickedEvent 를 편리하게 사용할 수 있다는 것이다.
이와 같은 내용을 확인해보기 위해서 위에서 사용한 [Serializable] 어트리뷰트가 사용되어 있는 상황과 해당 어트리뷰트를 제거한 상태를 비교하여서 첨부한다.
<첫째. [Serializable]이 사용된 상태>
<둘째. [Serializable]이 사용되지 않은 상태>
이렇듯 [Serializable] 어트리뷰트를 통해서 해당 클래스 혹은 구조체를 직렬화해서 유니티에서는 인스펙터 상에서 사용하기 쉽도록 노출시키고 수정할 수 있다. 물론 [Serializable] 을 사용하지 않고 AnimatedButton 클래스를 작성할때 코드적으로 이벤트에 +, _ 등을 사용해서 영향을 받을 메서드들을 등록해서 사용할 수 있겠으나, 그런 경우 변경사항이 생길시에 모두 클래스 스크립트를 수정해야하는 형태로 사용하는 것이기 때문에 해당 기능을 개발한 개발자 이외에 작성되어있는 클래스를 사용하는 사람의 경우 접근용이성이 떨어질 수 있을 것이다. 협업하는데 있어서도 위와 같이 직렬화를 통해서 인스펙터 상에서 보여지는것이 더욱 편할 것이고, 직렬화를 해놓고 인스펙터 창 자체에서 보는것이 해당 클래스를 열어보지 않은 상태에서도 더욱 직관적으로 해당 버튼에 엮여있는 이벤트를 전달받을 동작들을 이해하는데 용이할 것이다.
[Serializable] 어트리뷰트를 적재적소에 잘 활용해보도록 하자.
'Unity' 카테고리의 다른 글
스크립트 분리를 통한 OnDestroy() 메서드 실행 (0) | 2024.02.09 |
---|---|
유니티에서 프리팹 내보내기를 통한 다른 프로젝트의 프리팹 활용하기. (0) | 2024.02.07 |
오브젝트 풀에서 개체를 가져와서 특정 오브젝트의 자식들로 모아놓은뒤에, 다시 원래의 오브젝트 풀의 자식으로 옮기는 방법과 해당 방법을 구현하는 과정에서의 시행착오. (0) | 2024.02.03 |
오브젝트 풀 구성시 모든 풀을 담당하는 오브젝트에서 자식 오브젝트 모두를 순회하며 Pool 내부에 원하는 개체들을 Initialize 하는 방법에 대해서. (0) | 2024.01.30 |
유니티 오브젝트의 GetInstanceID() 함수를 이용한, 두 충돌 물체에서 한쪽에서만 원하는 로직이 실행되도록 만드는 방법. (0) | 2024.01.30 |