Version: 2021.3+
This example demonstrates how to create a list view runtime UI.
이 예시에서는 간단한 캐릭터 선택 화면을 생성합니다.왼쪽에 있는 리스트에서 캐릭터 이름을 클릭하면 캐릭터의 세부 정보가 오른쪽에 표시됩니다.
이 예시에서 생성한 완성된 파일은 GitHub 저장소에서 확인할 수 있습니다.
이 가이드는 Unity 에디터, UI 툴킷, C# 스크립팅에 익숙한 개발자용입니다.시작하기 전에 먼저 다음을 숙지하십시오.
* UXML
* ListView
* Label
* PanelSettings
* UIDocument
메인 뷰 UI 문서와 USS 파일을 생성하여 시각적 요소의 스타일을 지정합니다.UI 문서에서 두 개의 시각적 요소를 컨테이너로 추가합니다. 하나는 캐릭터 이름의 리스트를 포함하는 컨테이너이고 다른 하나는 선택한 캐릭터의 세부 정보를 포함하는 컨테이너입니다.
템플릿을 사용하여 Unity에서 프로젝트를 생성합니다.
프로젝트(Project) 창에서 UI
라는 이름의 폴더를 생성하여 모든 UI 문서와 스타일시트 파일을 저장합니다.
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:Button text="Select Character" display-tooltip-when-elided="true" name="select-char-button" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
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;
}
#select-char-button {
width: 150px;
border-color: rgb(49, 26, 17);
background-color: rgb(255, 133, 84);
border-width: 2px;
}
#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
폴더에 다음 콘텐츠가 포함된 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>
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의 캐릭터 리스트를 채울 샘플 데이터를 생성합니다.캐릭터 리스트의 경우 캐릭터 이름, 클래스, 세로 이미지가 포함된 클래스를 생성합니다.
Asset 폴더에 Scripts
라는 이름의 폴더를 만들어 C# 스크립트를 저장합니다.
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 m_CharacterName;
public ECharacterClass m_Class;
public Sprite m_PortraitImage;
}
이렇게 하면 Assets > Create 메뉴에 Character Data 항목이 생성됩니다.
Assets 폴더에 Resources
라는 이름의 폴더를 만듭니다.
Resources
폴더에 Characters
라는 이름의 폴더를 만들어 모든 샘플 캐릭터 데이터를 저장합니다.
Characters
폴더에서 오른쪽 클릭하고 Create > Character Data를 선택하여 ScriptableObject
의 인스턴스를 생성합니다.
CharacterData
인스턴스를 더 생성하고 플레이스홀더 데이터로 채웁니다.
SampleScene에서 UIDocument 게임 오브젝트를 생성하고 UI 문서를 소스 에셋으로 추가합니다.
다음 클래스를 포함한 두 개의 C# 스크립트를 생성합니다.
CharacterListEntryController
클래스.캐릭터 이름의 레이블에 액세스하여 지정된 캐릭터 인스턴스의 이름을 표시하도록 설정해야 합니다.
메인 뷰의 캐릭터 리스트를 위한 CharacterListController
클래스와 인스턴스화하고 시각적 트리에 할당하는 MonoBehaviour
스크립트.참고:CharacterListEntryController
클래스는 MonoBehaviour
가 아닙니다.UI 툴킷의 시각적 요소는 게임 오브젝트가 아니므로 컴포넌트를 연결할 수 없습니다.대신 CharacterListController
클래스의 userData
프로퍼티에 클래스를 연결합니다.
Scripts
폴더에 다음 콘텐츠가 포함된 CharacterListEntryController.cs
라는 이름의 C# 스크립트를 생성합니다.
using UnityEngine.UIElements;
public class CharacterListEntryController
{
Label m_NameLabel;
//This function retrieves a reference to the
//character name label inside the UI element.
public void SetVisualElement(VisualElement visualElement)
{
m_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)
{
m_NameLabel.text = characterData.m_CharacterName;
}
}
Scripts
폴더에 다음 콘텐츠가 포함된 CharacterListController.cs
라는 이름의 C# 스크립트를 생성합니다.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class CharacterListController
{
// UXML template for list entries
VisualTreeAsset m_ListEntryTemplate;
// UI element references
ListView m_CharacterList;
Label m_CharClassLabel;
Label m_CharNameLabel;
VisualElement m_CharPortrait;
public void InitializeCharacterList(VisualElement root, VisualTreeAsset listElementTemplate)
{
EnumerateAllCharacters();
// Store a reference to the template for the list entries
m_ListEntryTemplate = listElementTemplate;
// Store a reference to the character list element
m_CharacterList = root.Q<ListView>("character-list");
// Store references to the selected character info elements
m_CharClassLabel = root.Q<Label>("character-class");
m_CharNameLabel = root.Q<Label>("character-name");
m_CharPortrait = root.Q<VisualElement>("character-portrait");
FillCharacterList();
// Register to get a callback when an item is selected
m_CharacterList.onSelectionChange += OnCharacterSelected;
}
List<CharacterData> m_AllCharacters;
void EnumerateAllCharacters()
{
m_AllCharacters = new List<CharacterData>();
m_AllCharacters.AddRange(Resources.LoadAll<CharacterData>("Characters"));
}
void FillCharacterList()
{
// Set up a make item function for a list entry
m_CharacterList.makeItem = () =>
{
// Instantiate the UXML template for the entry
var newListEntry = m_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
m_CharacterList.bindItem = (item, index) =>
{
(item.userData as CharacterListEntryController).SetCharacterData(m_AllCharacters[index]);
};
// Set a fixed item height
m_CharacterList.fixedItemHeight = 45;
// Set the actual item's source list/array
m_CharacterList.itemsSource = m_AllCharacters;
}
void OnCharacterSelected(IEnumerable<object> selectedItems)
{
// Get the currently selected item directly from the ListView
var selectedCharacter = m_CharacterList.selectedItem as CharacterData;
// Handle none-selection (Escape to deselect everything)
if (selectedCharacter == null)
{
// Clear
m_CharClassLabel.text = "";
m_CharNameLabel.text = "";
m_CharPortrait.style.backgroundImage = null;
return;
}
// Fill in character details
m_CharClassLabel.text = selectedCharacter.m_Class.ToString();
m_CharNameLabel.text = selectedCharacter.m_CharacterName;
m_CharPortrait.style.backgroundImage = new StyleBackground(selectedCharacter.m_PortraitImage);
}
}
CharacterListController
는 MonoBehaviour
가 아니므로 시각적 트리에 연결해야 합니다.UIDocument와 동일한 게임 오브젝트에 연결할 수 있는 MonoBehaviour
스크립트를 생성합니다.CharacterListController
를 인스턴스화하여 시각적 트리에 연결합니다.
Scripts
폴더에 다음 콘텐츠가 포함된 MainView.cs
라는 이름의 C# 스크립트를 생성합니다.
using UnityEngine;
using UnityEngine.UIElements;
public class MainView : MonoBehaviour
{
[SerializeField]
VisualTreeAsset m_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, m_ListEntryTemplate);
}
}
SmpleScene에서 UIDocument를 선택합니다.
MainView.cs
를 인스펙터 창의 Add Component로 드래그합니다.
ListEntry.uxml을 ListEntry Template 필드로 드래그합니다.
플레이 모드로 전환하여 게임(Game) 뷰에 표시되는 UI를 확인합니다.