개요
-이 작업을 하게된 계기
효과음 사운드 적용 작업을 시작하게 됐는데
생각해보니 UI버튼에 사운드가 들어갈 대비를 미리 안했었다.
그래서 그 많은 UI에 일일히 사운드를 연결해줘야하나 고민하다가
Button 클래스를 상속받아 새로운 버튼 클래스를 만들어서 확장성을 넓히기로 결정했다.
본문
1. 일단 상속을 받아보자 !
먼저 Button 클래스를 냅다 상속받고 변수를 하나 추가한 뒤에 인스펙터를 확인해보자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.UI;
public class NT_Button : Button
{
[SerializeField]
private bool useDefaultButtonSound;
}
하지만 위와같이 선언한 변수가 어디에도 안보인다.
왜냐하면 Button 클래스는 ButtonEditor 클래스에의해 인스펙터가 커스텀 돼있다.
따라서 에디터 Draw 코드도 작성해야한다.
2. 에디터 코드를 추가해 보자!
그럼 이제 추가한 변수인 "bool userDefaultButtonSound"를 인스펙터에 노출시켜보자.
코드를 다음과 같이 수정하자
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.UI;
public class NT_Button : Button
{
[SerializeField]
private bool useDefaultButtonSound;
// 커스텀 변수를 그리기위한 Editor클래스
[CustomEditor(typeof(NT_Button))]
public class NT_ButtonEditor : SelectableEditor
{
private NT_Button btn;
SerializedProperty useDefaultSoundProperty;
SerializedProperty m_OnClickProperty; // 이거는 ButtonEditor에 있는거 복사해옴
protected override void OnEnable()
{
base.OnEnable();
m_OnClickProperty = serializedObject.FindProperty("m_OnClick");
// 여기까지하면 원래 Button이 나옴
useDefaultSoundProperty = serializedObject.FindProperty(nameof(btn.useDefaultButtonSound));
btn = target as NT_Button;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
EditorGUILayout.Space();
serializedObject.Update();
EditorGUILayout.PropertyField(m_OnClickProperty);
// 여기부터
EditorGUILayout.PropertyField(useDefaultSoundProperty);
// 여기까지 커스텀
serializedObject.ApplyModifiedProperties();
}
}
}
우선 원래 Button 컴포넌트의 인스펙터 형태도 유지하면서,
추가한 변수를 그리고 싶기 때문에
ButtonEditor 클래스에서 원래 Button 컴포넌트를 그리는 코드를 복사해왔다.
복사해온 코드에다가 필요한 변수들을 추가하고
bool 변수를
EditorGUILayout.PropertyField(useDefaultSoundProperty);
이렇게 직접 그려줬다.
이제 에디터를 보면
원하던 커스텀 변수가 노출된다!
3. 클릭했을 때 기능을 추가하자
이제 마지막으로 클릭했을때 디폴트 사운드를 출력시켜보자
override 함수 둘을 추가하자.
public override void OnPointerClick(PointerEventData eventData)
{
base.OnPointerClick(eventData);
// 디폴트 사운드를 사용하면 클릭했을때 자동 사운드 실행
if (useDefaultButtonSound)
SoundManager.Instance.PlaySfx("button");
}
public override void OnSubmit(BaseEventData eventData)
{
base.OnSubmit(eventData);
// 디폴트 사운드를 사용하면 클릭했을때 자동 사운드 실행
if (useDefaultButtonSound)
SoundManager.Instance.PlaySfx("button");
}
이제 클릭했을 때 디폴트 사운드가 체크돼있다면 디폴트 효과음을 출력시키게 된다.
부록. 에디터에서 Button => 커스텀 버튼 교체 컴포넌트 만들기
이제 커스텀 버튼도 만들었으니
Button컴포넌트를 전부 커스텀 버튼 컴포넌트로 교체해줘야 하는데
이벤트도 등록돼있을거고
인터랙트할때 컬러나 기타등등도 적용돼있을것이다.
그런 속성들을 유지하면서 편하게 옮겨보자
다음 코드를 작성한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Sirenix.OdinInspector;
using UnityEditor;
public class ButtonToNTButton : MonoBehaviour
{
[Button]
public void DoChangeComponent()
{
Button btn = GetComponent<Button>();
if (btn == null)
return;
var keptEvent = btn.onClick;
var keptGraphic = btn.targetGraphic;
var keptColors = btn.colors;
DestroyImmediate(btn);
var ntButton = gameObject.AddComponent<NT_Button>();
ntButton.onClick = keptEvent;
ntButton.targetGraphic = keptGraphic;
ntButton.colors = keptColors;
#if UNITY_EDITOR
EditorUtility.SetDirty(gameObject);
#endif
}
}
참고로,
[Button] 속성은
유료에셋을 사용하였는데
"naughty attributes"라는 무료에셋에도 같은 기능이 있다.
이제 Button에 방금 작성한 코드를 컴포넌트로 달고
버튼을 눌러보자.
Button이 커스텀 버튼으로 손쉽게 변경됐다!
결론
이렇게 최대한 편하게 만들긴 했지만
지금까지 만든 모든 버튼은 교체해주긴 해야한다.
다만,
그냥 버튼마다 클릭 이벤트에 사운드 호출을 연결했으면
사람이 해야할 일이니 실수를 할 확률도 무시할 수 없고,
앞으로 UI버튼에 공통 기능을 추가해야할 때 이 작업을 진행한게 빛을 발휘할 것이다.
'Unity > UI' 카테고리의 다른 글
[Unity] Grid Layout Group 좌우 여백 동적으로 균등하게 맞추기 (0) | 2024.06.11 |
---|---|
[Unity] UI 롱 클릭 이벤트 처리 with UniRx (0) | 2024.06.11 |
[Unity] UI드래그로 이동 시킬 때 범위 제한 (0) | 2022.08.29 |
[Unity] 마우스(포인터)가 UI위에 있는지 확인하기 (0) | 2022.05.11 |
[Unity] UI 클릭, 드래그이벤트 여러오브젝트 동시 처리 (0) | 2022.04.14 |