Version: 2022.2
언어: 한국어
스크롤 뷰 안에 콘텐츠 래핑
팝업 창 만들기

런타임용 탭 메뉴 생성

버전:2021.3+

탭 메뉴는 비디오 게임과 애플리케이션 UI에서 흔히 볼 수 있습니다. UI 툴킷을 사용하여 커스텀 에디터 창 또는 런타임용 탭 메뉴를 만들 수 있습니다. 다음 예시는 샘플 씬에서 탭 메뉴를 만드는 방법을 보여줍니다.

개요 예시

이 예시에서는 샘플 씬에 메뉴를 추가합니다. 메뉴에는 세 개의 탭이 있습니다. 각 탭에는 특정 콘텐츠가 표시됩니다. 탭을 클릭하면 해당 탭과 연결된 콘텐츠만 표시됩니다.

탭 메뉴 미리보기
탭 메뉴 미리보기

탭 콘텐츠를 만들려면 메뉴 요소, 스타일, 로직을 정의해야 합니다.

이 예시에서 생성한 완성된 파일은 GitHub 저장소에서 확인할 수 있습니다.

선행 조건

이 가이드는 Unity, UI 툴킷, Flexbox, C# 스크립팅에 익숙한 개발자용입니다.시작하기 전에 먼저 다음을 숙지하십시오.

탭 메뉴 요소 정의

UI 빌더를 사용하여 메뉴에 섹션 2개를 만듭니다. 하나는 탭용이고 다른 하나는 탭 콘텐츠용입니다. 이 섹션에 탭 요소 3개와 탭 콘텐츠 요소 3개를 만듭니다.

  1. 템플릿을 사용하여 Unity에서 프로젝트를 생성합니다.

  2. GameObject > UI Toolkit > UI Document를 클릭하여 샘플 씬에 UI 문서를 추가합니다

  3. AssetsTabbedMenu라는 이름의 폴더를 만들어 모든 파일을 저장합니다.

  4. TabbedMenu 폴더에 TabbedMenu.uxml이라는 이름의 UI 문서를 생성합니다.

  5. TabbedMenu.uxml을 더블 클릭하여 UI 빌더에서 엽니다.

  6. 루트 아래에 tabstabContent라는 이름의 VisualElement 두 개를 추가합니다.

  7. Tabs 아래에 세 개의 레이블 컨트롤을 추가하고 다음 레이블 텍스트를 부여합니다.

    • London
    • Paris
    • Ottawa
  8. tabContent 아래에 레이블 컨트롤 3개를 추가하고 레이블 텍스트를 다음과 같이 지정합니다.

    • London is the capital city of England
    • Paris is the capital of France
    • Ottawa is the capital of Canada
  9. 탭 콘텐츠를 탭과 연결하기 위해 이 예시에서는 레이블 이름의 접두사를 동일하게 사용하고 접미사를 다르게 사용합니다. 각 탭 이름에는 Tab 접미사가 있고 각 탭 콘텐츠에는 Content 접미사가 있습니다. 탭 레이블 이름과 콘텐츠 레이블 이름을 다음과 같이 설정합니다.

    • LondonTab
    • ParisTab
    • OttawaTab
    • LondonContent
    • ParisContent
    • OttawaContent

UI 빌더 계층 구조는 다음과 같이 표시됩니다.

UI 빌더 계층 구조
UI 빌더 계층 구조

탭 메뉴 스타일 정의

USS를 사용하여 탭과 탭 콘텐츠의 레이아웃을 정의합니다. 원하는 방식으로 탭과 탭 콘텐츠의 스타일을 지정할 수 있습니다. 이 예시에서는 탭을 탭 콘텐츠의 상단에 행으로 정렬합니다. 선택한 탭의 배경색을 추가하고 선택하지 않은 탭 콘텐츠를 숨깁니다.

  1. TabbedMenu 폴더에 TabbedMenu.uss라는 이름의 스타일시트를 생성합니다.

  2. TabbedMenu.uss를 열고 다음 스타일 규칙을 추가합니다.

    /* Style for tabs */
    #tabs {
        flex-direction: row;
        background-color: rgb(229, 223, 223);
        -unity-font-style: bold;
        font-size:14px;
    }
    
    /* Sets each label in tabs to have the same size.*/
    .tab {
        flex-grow:1;
    }
    
    /* Adds background color for the selected tab */
    .currentlySelectedTab {
        background-color: rgb(173, 166, 166);
    }
    
    /* Style for tabContent */
    #tabContent {
        background-color: rgb(255, 255, 255);
        font-size:20px;
    }
    
    /* Hides the unselected tab content */
    .unselectedContent {
        display: none;
    }
    
  3. UI 빌더에서 TabbedMenu.uxml을 엽니다.

  4. Add Existing USS를 클릭하고 TabbedMenu.uss를 선택합니다.

  5. UI 컨트롤에 스타일을 적용합니다.

    • tabs아래의 각 레이블에 .tab을 적용합니다.
    • LondonTab.currentlySelectedTab을 적용합니다.
    • ParisContentOttawaContent.unselectedContent를 적용합니다.

완료된 TabbedMenu.uxml은 다음과 같이 표시됩니다.

<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">
   /* Your src might look different.If you save your UXML in UI Builder, USS file is referenced by the file location, fileID and guid.*/
   <Style src="TabbedMenu-style.uss" />
   <ui:VisualElement>
        <ui:VisualElement name="tabs">
            <ui:Label name="LondonTab" text="London" class="tab currentlySelectedTab" />
            <ui:Label name="ParisTab" text="Paris" class="tab" />
            <ui:Label name="OttawaTab" text="Ottawa" class="tab" />
        </ui:VisualElement>
        <ui:VisualElement name="tabContent">
            <ui:Label text="London is the capital city of England" name="LondonContent" />
            <ui:Label text="Paris is the capital of France" name="ParisContent" class="unselectedContent" />
            <ui:Label text="Ottawa is the capital of Canada" name="OttawaContent" class="unselectedContent" />
        </ui:VisualElement>
   </ui:VisualElement>
</ui:UXML>

씬 설정

SampleScene에서 UIDocument 게임 오브젝트를 생성하고 UI 문서를 소스 에셋으로 추가합니다.

  1. SampleScene에서 GameObject > UI Toolkit > UI Document를 선택합니다.
  2. 계층 구조에서 UIDocument 게임 오브젝트를 선택하고 TabbedMenu.uxml을 프로젝트(Project) 창에서 인스펙터(Inspector) 창의 UI Document 컴포넌트의 Source Asset 필드로 드래그합니다.이는 소스 에셋을 생성한 UXML 파일로 참조합니다.

탭 메뉴 로직 정의

표시된 탭 콘텐츠를 변경하는 C# 스크립트를 생성합니다.사용자가 탭을 클릭하면 탭의 콘텐츠가 표시되고 현재 콘텐츠는 숨겨집니다.탭한 메뉴 로직을 게임에 연결하는 MonoBehaviour 스크립트를 생성합니다.

  1. TabbedMenu 폴더에 다음 콘텐츠가 있는 TabbedMenuController.cs라는 이름의 C# 스크립트를 생성합니다.

    // This script defines the tab selection logic.
    using UnityEngine.UIElements;
    
    public class TabbedMenuController
    {
        /* Define member variables*/
        private const string tabClassName = "tab";
        private const string currentlySelectedTabClassName = "currentlySelectedTab";
        private const string unselectedContentClassName = "unselectedContent";
        // Tab and tab content have the same prefix but different suffix
        // Define the suffix of the tab name
        private const string tabNameSuffix = "Tab";
        // Define the suffix of the tab content name
        private const string contentNameSuffix = "Content";
    
        private readonly VisualElement root;
    
        public TabbedMenuController(VisualElement root)
        {
            this.root = root;
        }
    
        public void RegisterTabCallbacks()
        {
            UQueryBuilder<Label> tabs = GetAllTabs();
            tabs.ForEach((Label tab) => {
                tab.RegisterCallback<ClickEvent>(TabOnClick);
            });
        }
    
        /* Method for the tab on-click event:
    
           - If it is not selected, find other tabs that are selected, unselect them 
           - Then select the tab that was clicked on
        */
        private void TabOnClick(ClickEvent evt)
        {
            Label clickedTab = evt.currentTarget as Label;
            if (!TabIsCurrentlySelected(clickedTab))
            {
                GetAllTabs().Where(
                    (tab) => tab != clickedTab && TabIsCurrentlySelected(tab)
                ).ForEach(UnselectTab);
                SelectTab(clickedTab);
            }
        }
        //Method that returns a Boolean indicating whether a tab is currently selected
        private static bool TabIsCurrentlySelected(Label tab)
        {
            return tab.ClassListContains(currentlySelectedTabClassName);
        }
    
        private UQueryBuilder<Label> GetAllTabs()
        {
            return root.Query<Label>(className: tabClassName);
        }
    
        /* Method for the selected tab:
           -  Takes a tab as a parameter and adds the currentlySelectedTab class
           -  Then finds the tab content and removes the unselectedContent class */
        private void SelectTab(Label tab)
        {
            tab.AddToClassList(currentlySelectedTabClassName);
            VisualElement content = FindContent(tab);
            content.RemoveFromClassList(unselectedContentClassName);
        }
    
        /* Method for the unselected tab:
           -  Takes a tab as a parameter and removes the currentlySelectedTab class
           -  Then finds the tab content and adds the unselectedContent class */
        private void UnselectTab(Label tab)
        {
            tab.RemoveFromClassList(currentlySelectedTabClassName);
            VisualElement content = FindContent(tab);
            content.AddToClassList(unselectedContentClassName);
        }
    
        // Method to generate the associated tab content name by for the given tab name
        private static string GenerateContentName(Label tab) =>
            tab.name.Replace(tabNameSuffix, contentNameSuffix);
    
        // Method that takes a tab as a parameter and returns the associated content element
        private VisualElement FindContent(Label tab)
        {
            return root.Q(GenerateContentName(tab));
        }
    }
    
  2. TabbedMenu 폴더에 다음 콘텐츠가 있는 TabbedMenu.cs라는 이름의 C# 스크립트를 생성합니다.

    // This script attaches the tabbed menu logic to the game.
    using UnityEngine;
    using UnityEngine.UIElements;
    
    //Inherits from class `MonoBehaviour`.This makes it attachable to a game object as a component.
    public class TabbedMenu :MonoBehaviour
    {
        private TabbedMenuController controller;
    
        private void OnEnable()
        {
            UIDocument menu = GetComponent<UIDocument>();
            VisualElement root = menu.rootVisualElement;
    
            controller = new(root);
    
            controller.RegisterTabCallbacks();
        }
    }
    
  3. SampleScene에서 UIDocument를 선택하고 TabbedMenu.cs를 인스펙터의 Add Component로 드래그합니다.

  4. 플레이 모드로 전환하고 다른 탭을 클릭하여 다른 콘텐츠를 확인합니다.

추가 리소스

스크롤 뷰 안에 콘텐츠 래핑
팝업 창 만들기