Animated Button 클래스를 구현할때 [Serializable] 의 사용 유무에 따른 유니티 인스펙터에서의 차이점.

버튼을 클릭시에 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] 어트리뷰트가 사용되어서 직렬화 되어서 인스펙터 창에서 쉽게 설정할 수 있는 모습. On Click() 이 보이고 해당 내용에 대해서 추가삭제가 편리하게 되어있다.

 

<둘째. [Serializable]이 사용되지 않은 상태>

[Serializable] 어트리뷰트를 제거한 상태. 이 경우 인스펙터 창에서 해당 UnityEvent를 상속한 ButtonClickedEvent 를 인스턴스화해서 사용시에 인스펙터 창에서 쉽게 편집할 수 있는 창이 나타나지 않는다.

 

 

이렇듯 [Serializable] 어트리뷰트를 통해서 해당 클래스 혹은 구조체를 직렬화해서 유니티에서는 인스펙터 상에서 사용하기 쉽도록 노출시키고 수정할 수 있다. 물론 [Serializable] 을 사용하지 않고 AnimatedButton 클래스를 작성할때 코드적으로 이벤트에 +, _ 등을 사용해서 영향을 받을 메서드들을 등록해서 사용할 수 있겠으나, 그런 경우 변경사항이 생길시에 모두 클래스 스크립트를 수정해야하는 형태로 사용하는 것이기 때문에 해당 기능을 개발한 개발자 이외에 작성되어있는 클래스를 사용하는 사람의 경우 접근용이성이 떨어질 수 있을 것이다. 협업하는데 있어서도 위와 같이 직렬화를 통해서 인스펙터 상에서 보여지는것이 더욱 편할 것이고, 직렬화를 해놓고 인스펙터 창 자체에서 보는것이 해당 클래스를 열어보지 않은 상태에서도 더욱 직관적으로 해당 버튼에 엮여있는 이벤트를 전달받을 동작들을 이해하는데 용이할 것이다. 

 

[Serializable] 어트리뷰트를 적재적소에 잘 활용해보도록 하자. 

 

  Comments,     Trackbacks