Version: 2023.1
언어: 한국어
복합 리스트 뷰 생성
스크롤 뷰 안에 콘텐츠 래핑

리스트 뷰 런타임 UI 생성

버전:2021.3+

이 예시는 리스트 뷰 런타임 UI 생성 방법을 보여줍니다.이 예시에서는 UXML과 USS 파일을 직접 사용하여 UI의 구조와 스타일을 생성합니다.UI 툴킷을 처음 사용하고 UI 빌더를 사용하여 UI를 생성하려는 경우, UI 빌더로 예시 UI 생성을 참조하십시오.

개요 예시

이 예시에서는 간단한 캐릭터 선택 화면을 생성합니다.왼쪽에 있는 리스트에서 캐릭터 이름을 클릭하면 캐릭터의 세부 정보가 오른쪽에 표시됩니다.

런타임 UI의 최종 뷰
런타임 UI의 최종 뷰

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

선행 조건

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

메인 UI 문서 생성

메인 뷰 UI 문서와 USS 파일을 생성하여 시각적 요소의 스타일을 지정합니다.UI 문서에서 두 개의 시각적 요소를 컨테이너로 추가합니다. 하나는 캐릭터 이름의 리스트를 포함하는 컨테이너이고 다른 하나는 선택한 캐릭터의 세부 정보를 포함하는 컨테이너입니다.

메인 뷰의 UI 레이아웃 설정
메인 뷰의 UI 레이아웃 설정
  1. 템플릿을 사용하여 Unity에서 프로젝트를 생성합니다.

  2. 프로젝트(Project) 창에서 UI라는 이름의 폴더를 생성하여 모든 UI 문서와 스타일시트 파일을 저장합니다.

  3. UI 폴더에 다음 콘텐츠가 포함된 MainView.uxml이라는 이름의 UI 문서를 생성합니다.

    <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
    <Style src="MainView.uss" />
    <ui:VisualElement name="background">
        <ui:VisualElement name="main-container">
            <ui:ListView focusable="true" name="character-list" />
            <ui:VisualElement name="right-container">
                <ui:VisualElement name="details-container">
                    <ui:VisualElement name="details">
                        <ui:VisualElement name="character-portrait" />
                    </ui:VisualElement>
                    <ui:Label text="Label" name="character-name" />
                    <ui:Label text="Label" display-tooltip-when-elided="true" name="character-class" />
                </ui:VisualElement>
            </ui:VisualElement>
        </ui:VisualElement>
    </ui:VisualElement>
    </ui:UXML>
    
  4. UI 폴더에 다음 콘텐츠가 포함된 MainView.uss라는 이름의 USS 스타일시트를 생성합니다.

        #background {
                flex-grow: 1;
                align-items: center;
                justify-content: center;
                background-color: rgb(115, 37, 38);
            }
    
            #main-container {
                flex-direction: row;
                height: 350px;
            }
    
            #character-list {
                width: 230px;
                border-color: rgb(49, 26, 17);
                border-width: 4px;
                background-color: rgb(110, 57, 37);
                border-radius: 15px;
                margin-right: 6px;
            }
    
            #character-name {
                -unity-font-style: bold;
                font-size: 18px;
            }
    
            #CharacterClass {
                margin-top: 2px;
                margin-bottom: 8px;
                padding-top: 0;
                padding-bottom: 0;
            }
    
            #right-container{
                justify-content: space-between;
                align-items: flex-end;
            }
    
            #details-container{
                align-items: center;
                background-color: rgb(170, 89, 57);
                border-width: 4px;
                border-color: rgb(49, 26, 17);
                border-radius: 15px;
                width: 252px;
                justify-content: center;
                padding: 8px;
                height: 163px;
            }
    
            #details{
                border-color: rgb(49, 26, 17);
                border-width: 2px;
                height: 120px;
                width: 120px;
                border-radius: 13px;
                padding: 4px;
                background-color: rgb(255, 133, 84);
            }
    
            #character-portrait{
                flex-grow: 1;
                -unity-background-scale-mode: scale-to-fit;
            }
    

리스트 엔트리 UI 문서 생성

리스트의 개별 엔트리에 대한 UI 문서와 스타일시트를 생성합니다.캐릭터 리스트 엔트리는 컬러 배경 프레임과 캐릭터 이름으로 구성됩니다.

캐릭터 이름이 표시되는 리스트 엔트리
캐릭터 이름이 표시되는 리스트 엔트리
  1. UI 폴더에 다음 콘텐츠가 포함된 ListEntry.uxml이라는 이름의 UI 문서를 생성합니다.

    <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
    <Style src="ListEntry.uss" />
    <ui:VisualElement name="list-entry">
        <ui:Label text="Label" display-tooltip-when-elided="true" name="character-name" />
    </ui:VisualElement>
    </ui:UXML>
    
  2. UI 폴더에 다음 콘텐츠가 포함된 ListEntry.uss라는 이름의 스타일시트 파일을 생성합니다.

        #list-entry {
                height:41px;
                align-items: flex-start;
                justify-content: center;
                padding-left:10px;
                background-color: rgb(170, 89, 57);
                border-color: rgb(49, 26, 17);
                border-width:2px;
                border-radius:15px;
            }
    
            #character-name {
                -unity-font-style: bold;
                font-size:18px;
                color: rgb(49, 26, 17);
            }
    

표시할 샘플 데이터 만들기

UI의 캐릭터 리스트를 채울 샘플 데이터를 생성합니다.캐릭터 리스트의 경우 캐릭터 이름, 클래스, 세로 이미지가 포함된 클래스를 생성합니다.

  1. Asset 폴더에 Scripts라는 이름의 폴더를 만들어 C# 스크립트를 저장합니다.

  2. Scripts 폴더에 다음 콘텐츠가 포함된 CharacterData.cs라는 이름의 C# 스크립트를 생성합니다.

    using UnityEngine;
    
    public enum ECharacterClass
    {
        Knight, Ranger, Wizard
    }
    
    [CreateAssetMenu] //This adds an entry to the **Create** menu
    public class CharacterData :ScriptableObject
    {
        public string CharacterName;
        public ECharacterClass Class;
        public Sprite PortraitImage;
    }
    

    이렇게 하면 Assets > Create 메뉴에 Character Data 항목이 생성됩니다.

  3. Assets 폴더에 Resources라는 이름의 폴더를 만듭니다.

  4. Resources 폴더에 Characters라는 이름의 폴더를 만들어 모든 샘플 캐릭터 데이터를 저장합니다.

  5. Characters 폴더에서 오른쪽 클릭하고 Create > Character Data를 선택하여 ScriptableObject의 인스턴스를 생성합니다.

  6. CharacterData 인스턴스를 더 생성하고 플레이스홀더 데이터로 채웁니다.

씬 설정

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

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

리스트 엔트리 및 메인 뷰의 컨트롤러 생성

다음 클래스를 포함한 두 개의 C# 스크립트를 생성합니다.

  • 리스트 엔트리의 UI에 캐릭터 인스턴스의 데이터를 표시하는 CharacterListEntryController 클래스.캐릭터 이름의 레이블에 액세스하여 지정된 캐릭터 인스턴스의 이름을 표시하도록 설정해야 합니다. 메인 뷰의 캐릭터 리스트를 위한 CharacterListController 클래스와 인스턴스화하고 시각적 트리에 할당하는 MonoBehaviour 스크립트.

참고:CharacterListEntryController 클래스는 MonoBehaviour가 아닙니다.UI 툴킷의 시각적 요소는 게임 오브젝트가 아니므로 컴포넌트를 연결할 수 없습니다.대신 CharacterListController 클래스의 userData 프로퍼티에 클래스를 연결합니다.

  1. Scripts 폴더에 다음 콘텐츠가 포함된 CharacterListEntryController.cs라는 이름의 C# 스크립트를 생성합니다.

    using UnityEngine.UIElements;
    
    public class CharacterListEntryController
    {
        Label NameLabel;
    
        //This function retrieves a reference to the
        //character name label inside the UI element.
    
        public void SetVisualElement(VisualElement visualElement)
        {
            NameLabel = visualElement.Q<Label>("character-name");
        }
    
        //This function receives the character whose name this list
        //element displays. Since the elements listed
        //in a `ListView` are pooled and reused, it's necessary to
        //have a `Set` function to change which character's data to display.
    
        public void SetCharacterData(CharacterData characterData)
        {
            NameLabel.text = characterData.CharacterName;
        }
    }
    
  2. Scripts 폴더에 다음 콘텐츠가 포함된 CharacterListController.cs라는 이름의 C# 스크립트를 생성합니다.

    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UIElements;
    
    public class CharacterListController
    {
        // UXML template for list entries
        VisualTreeAsset ListEntryTemplate;
    
        // UI element references
        ListView CharacterList;
        Label CharClassLabel;
        Label CharNameLabel;
        VisualElement CharPortrait;
    
        public void InitializeCharacterList(VisualElement root, VisualTreeAsset listElementTemplate)
        {
            EnumerateAllCharacters();
    
            // Store a reference to the template for the list entries
            ListEntryTemplate = listElementTemplate;
    
            // Store a reference to the character list element
            CharacterList = root.Q<ListView>("character-list");
    
            // Store references to the selected character info elements
            CharClassLabel = root.Q<Label>("character-class");
            CharNameLabel = root.Q<Label>("character-name");
            CharPortrait = root.Q<VisualElement>("character-portrait");
    
            FillCharacterList();
    
            // Register to get a callback when an item is selected
            CharacterList.onSelectionChange += OnCharacterSelected;
        }
    
        List<CharacterData> AllCharacters;
    
        void EnumerateAllCharacters()
        {
            AllCharacters = new List<CharacterData>();
            AllCharacters.AddRange(Resources.LoadAll<CharacterData>("Characters"));
        }
    
        void FillCharacterList()
        {
            // Set up a make item function for a list entry
            CharacterList.makeItem = () =>
            {
                // Instantiate the UXML template for the entry
                var newListEntry = ListEntryTemplate.Instantiate();
    
                // Instantiate a controller for the data
                var newListEntryLogic = new CharacterListEntryController();
    
                // Assign the controller script to the visual element
                newListEntry.userData = newListEntryLogic;
    
                // Initialize the controller script
                newListEntryLogic.SetVisualElement(newListEntry);
    
                // Return the root of the instantiated visual tree
                return newListEntry;
            };
    
            // Set up bind function for a specific list entry
            CharacterList.bindItem = (item, index) =>
            {
                (item.userData as CharacterListEntryController).SetCharacterData(AllCharacters[index]);
            };
    
            // Set a fixed item height
            CharacterList.fixedItemHeight = 45;
    
            // Set the actual item's source list/array
            CharacterList.itemsSource = AllCharacters;
        }
    
        void OnCharacterSelected(IEnumerable<object> selectedItems)
        {
            // Get the currently selected item directly from the ListView
            var selectedCharacter = CharacterList.selectedItem as CharacterData;
    
            // Handle none-selection (Escape to deselect everything)
            if (selectedCharacter == null)
            {
                // Clear
                CharClassLabel.text = "";
                CharNameLabel.text = "";
                CharPortrait.style.backgroundImage = null;
    
                return;
            }
    
            // Fill in character details
            CharClassLabel.text = selectedCharacter.Class.ToString();
            CharNameLabel.text = selectedCharacter.CharacterName;
            CharPortrait.style.backgroundImage = new StyleBackground(selectedCharacter.PortraitImage);
        }
    }
    

메인 뷰에 컨트롤러 스크립트 연결

CharacterListControllerMonoBehaviour가 아니므로 시각적 트리에 연결해야 합니다.UIDocument와 동일한 게임 오브젝트에 연결할 수 있는 MonoBehaviour 스크립트를 생성합니다.CharacterListController를 인스턴스화하여 시각적 트리에 연결합니다.

  1. Scripts 폴더에 다음 콘텐츠가 포함된 MainView.cs라는 이름의 C# 스크립트를 생성합니다.

    using UnityEngine;
    using UnityEngine.UIElements;
    
    public class MainView :MonoBehaviour
    {
        [SerializeField]
        VisualTreeAsset ListEntryTemplate;
    
        void OnEnable()
        {
            // The UXML is already instantiated by the UIDocument component
            var uiDocument = GetComponent<UIDocument>();
    
            // Initialize the character list controller
            var characterListController = new CharacterListController();
            characterListController.InitializeCharacterList(uiDocument.rootVisualElement, ListEntryTemplate);
        }
    }
    
  2. SmpleScene에서 UIDocument를 선택합니다.

  3. MainView.cs를 인스펙터 창의 Add Component로 드래그합니다.

  4. ListEntry.uxmlListEntry Template 필드로 드래그합니다.

  5. 플레이 모드로 전환하여 게임(Game) 뷰에 표시되는 UI를 확인합니다.

추가 리소스

복합 리스트 뷰 생성
스크롤 뷰 안에 콘텐츠 래핑