UI Toolkit으로 라디오 버튼 관련 작업을 하며 레퍼런스의 부족으로 많이 헤맸었다. 그래서 간략히 정리해보고자 한다.
참고 자료
https://www.foundations.unity.com/components/radio-button#Radio-Button-Group
https://docs.unity3d.com/ScriptReference/UIElements.RadioButton.html
https://docs.unity3d.com/ScriptReference/UIElements.RadioButtonGroup.html
다양한 선택지가 주어질 때 오직 한 가지 선택만 가능하도록 설정할 때 사용되는 버튼이다.
기존에 UGUI 방식으로는 Radio Button과 Radio Button Group을 위해 Toggle과 Toggle Group을 이용해 구현하였다. (기존에 reference들이 많아서 해당 포스트에서는 따로 다루지 않는다.)
크게 라디오 버튼 그룹과 그룹 박스로 라디오 버튼을 관리한다. 그룹으로 묶인 라디오 버튼들 내에서 한 가지 라디오 버튼만 선택 가능하게 된다.
❓ 라디오 버튼 그룹과 그룹 박스의 차이
라디오 버튼 그룹의 경우 라디오 버튼만 포함시킬 수 있다. 또한 레이아웃 자체가 이미 정의되어 있어 hiearchy 창에서의 자유로운 커스텀을 제공하지 않는다. (주로 USS 파일에 직접 접근해서 내부 설정들을 변경할 수 있으며, 라디오 버튼을 그룹에 포함시키기 위해 UXML 스크립트를 건들여야 한다.)
그룹 박스는 라디오 버튼과 text field 등 다른 요소들도 넣을 수 있다. 유저가 레이아웃 자체를 커스텀하게 설정할 수 있다. (즉, hiearchy 상에서 원하는 대로 배치 가능한데 radio button group에서 라디오 버튼에 대해 제공하는 일부 function이 없다.)
상황에 맞게 어떤 것으로 라디오 버튼들을 그룹화할 것인지 결정하면 된다. 본 포스트에서는 Radio button group을 기반으로 한 라디오 버튼 동작에 대해 다룬다.
앞서 말했듯 라디오 버튼 그룹은 이미 정의된 틀을 제공하기에 hierarchy 창에서의 수정이 막혀있는 것을 확인할 수 있다.
하지만 기본적인으로 제공되는 틀에서 일부 배치 수정을 원할 수 있다. 그럴때는 hiearchy창 대신 style class에 접근해서 수정해야한다.
RadioButtonGroup
↳ Label
↳ VisualElement
라디오 버튼 그룹을 기본적으로 구성하는 style class들이다.
🔹 .unity-radio-button-group
기본적으로 라디오 버튼 그룹을 생성했을 때 inspector에서 보이는 값이다. (inspector창 자체로 수정이 가능하기 때문에 여러 곳에 적용을 위함이 아니면 따로 uss로 작업할 필요는 없다.)
🔹 .unity-base-field__input (라디오 버튼 그룹에만 적용되는 것은 x -> 따로 custom하게 정의 필요)
라디오 버튼들을 담고 있는 VisualElement가 가지고 있는 style class이다. 해당 스타일 클래스의 경우 유니티에서 기본적으로 제공하는 Controls들의 일부 오브젝트들이 공유하고 있기 때문에 주의해서 변경해야한다.
라디오 버튼 그룹에서는 라디오 버튼들을 담고 있는 VisualElement이기 때문에 라디오 버튼들의 align 등을 결정할 때 사용할 수 있다.
RadioButton
↳ Label
↳ VisualElement
↳↳ VisualElement
↳↳↳ VisualElement (#unity-checkmark)
라디오 버튼을 기본적으로 구성하는 style class들이다.
🔹 .unity-radio-button
공통 라디오 버튼에 대한 style class이다. 기본적으로 radio button을 생성했을 때 inspector에서 보이는 값이라고 보면 된다. (이 부분은 inspector창 자체로 수정 가능하기 때문에 한 라디오 버튼에 대해 작업하는 경우라면 굳이 uss로 따로 작업할 필요는 없다.)
주로 size, align, position 값을 설정한다. (크기, 가로 또는 세로 배치 결정, 전체 위치 결정)
🔹 .unity-radio-button__input
뒤에 소개할 라디오 버튼의 style class 중 버튼 모양을 바꾸는 것과 연관된 두 클래스의 부모로 잡혀있는 Visual Element의 style class이다.
따라서 주로 버튼의 위치를 조정하고 싶을 때 해당 클래스로 접근해 position을 변경해주면 된다. 추가로 앞서 말했듯 버튼 모양이 Overflow로 잘려있는 경우 여기서 Overflow를 visible로 해주면 된다.
🔹 .unity-radio-button__checkmark-background
라디오 버튼에서 누르기 전에 기본적으로 보이는 style을 나타낸다. Background와 Border에 기본적으로 설정된 값이 있기 때문에 해당 부분을 custom하면 원하는 라디오 버튼 이미지를 넣을 수 있다.
🔹 .unity-radio-button__checkmark
라디오 버튼이 눌렸을 때의 style을 나타낸다. 원하는 이미지를 넣거나 color를 바꾸며 커스텀할 수 있다.
각 style class는 uss 파일 내의 클래스를 정의해 변경할 수 있다. (추후 uss와 uxml 사용하는 부분 정리해보고자 한다.) 기본적으로 유니티 라이브러리에서 가져올 수 있는 UI 요소들의 style class 정보는 inspector 창의 style class list에서 확인할 수 있다. 또한 요소 중 자식들을 들고 있는 경우 자식들의 style class도 확인해가며 Viewport 화면에서 어떤 부분에 변화를 줄지 대략적인 파악이 가능하다. (+ 플레이 타임에서 UI Toolkit Debugger로도 확인할 수 있다.)
일반적으로 어떤 라디오 버튼이 클릭되어 있는지에 대한 정보를 가져와 로직을 짜게 된다. 먼저 라디오 버튼을 라디오 버튼 그룹에서 인식할 수 있도록 하기 위해 UXML 스크립트에서 일부 내용을 추가해주어야한다.
❗ 주의할 점
다음과 같이 단순히 UXML에 Radio Button을 드래그 앤 드롭식으로 추가하는 방식으로는 그룹 내의 라디오 버튼으로 스크립트 상 인식하지 못한다! (일반적인 버튼처럼 UXML 화면에서 집어넣고 동작이 안되어서 시간 많이 썼는데 현재 이런 방식으론 동작 안한다는 unity의 답변이 달린 글을 보았다.)
UXML 상에서 Radio Button Group 내에 Radio Button 추가하기
UXML 상에서 Radio Button Group을 Hierarchy에 추가하고 UXML 코드를 확인해보자.
(코드는 스크립트 에디터 자체에서도 접근할 수 있고 유니티에서는 UXML 파일 옆 화살표를 누르면 나오는 inlineStyle을 클릭해서 열 수 있다.)
기본적으로 작성되어 있는 UXML 코드는 다음과 같다. 코드 상 RadioButtonGroup의 value가 -1이 되어있는 것을 확인할 수 있는데 현재 아무것도 선택되지 않았다는 의미를 가진다.
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:VisualElement name="container" style="flex-grow: 1; flex-shrink: 0;">
<ui:RadioButtonGroup label="Radio Button Group" value="-1" name="radio-button-group" />
</ui:VisualElement>
</ui:UXML>
라디오 버튼을 라디오 버튼 그룹에 추가하기 위해서는 다음과 같이 choices로 명시해주어야 한다. (기본 선택 값을 choice 1으로 주기 위해 value도 0으로 변경하였다.)
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:VisualElement name="container" style="flex-grow: 1; flex-shrink: 0;">
<ui:RadioButtonGroup choices="choice1, choice2, choice3" label="Radio Button Group" value="0" name="radio-button-group" />
</ui:VisualElement>
</ui:UXML>
코드로 UXML 상 라디오 버튼을 추가하면 그룹의 value에 접근해 현재 클릭되어있는 라디오 버튼의 인덱스 값을 가져올 수 있다. 이외에 다른 기능들을 보고 싶으면 위에 참고 자료에 첨부한 radio button group의 scripting API를 참고하면 된다.
이제 C# 스크립트로 UI Toolkit에서 라디오 버튼 그룹에서 어떤 라디오 버튼이 클릭되어 있는지 확인하는 코드를 작성할 차례다.
using UnityEngine;
using UnityEngine.UIElements;
public class RadioButton : MonoBehaviour
{
private RadioButtonGroup radioButtonGroup;
private void Awake()
{
VisualElement root = GetComponent<UIDocument>().rootVisualElement;
VisualElement container = root.Q<VisualElement>("container");
radioButtonGroup = container.Q<RadioButtonGroup>("radio-button-group");
}
private void OnEnable()
{
// 라디오 버튼 그룹에서 다른 버튼 클릭될 때 함수 실행
radioButtonGroup.RegisterValueChangedCallback(evt => PrintClickedRadioButton());
}
private void PrintClickedRadioButton()
{
Debug.Log("현재 클릭된 버튼" + radioButtonGroup.value);
}
}
최종적으로 라디오 버튼 그룹에서 라디오 버튼의 동작이 되는 모습이다.
덕분에 많이 배웠습니다 감사합니다!