프리팹은 씬에서 여러 번 인스턴스화할 수 있는 사전 제작된 게임 오브젝트입니다. 프리팹은 재사용 가능한 컴포넌트를 생성하는 데 유용합니다. UI 툴킷의 시각적 요소는 게임 오브젝트가 아니므로 프리팹은 적용되지 않습니다. 하지만 로직으로 요소의 특정 계층 구조를 캡슐화하는 재사용 가능한__ UI__(사용자 인터페이스) 사용자가 애플리케이션과 상호 작용하도록 해 줍니다. Unity는 현재 3개의 UI 시스템을 지원합니다. 자세한 정보
See in Glossary 컴포넌트로 커스텀 컨트롤을 생성할 수 있습니다. UI 툴킷은 게임이나 애플리케이션 코드에서 UI를 분리하도록 합니다. 따라서 UXML을 사용하여 구조를 정의하고, USS를 사용하여 모양을 정의하고, C#을 사용하여 커스텀 컨트롤의 로직을 정의할 수 있습니다.
예를 들어 카드 게임을 만들고 싶다고 가정해 보겠습니다. 생명력, 공격력과 같은 다양한 통계가 포함된 카드를 표시하려고 합니다.
캐릭터의 이미지, 생명력, 공격력 통계를 표시하는 CardElement라는 커스텀 컨트롤을 생성한 다음, 게임의 각 카드에 이 커스텀 컨트롤을 재사용할 수 있습니다.
다음은 이를 수행하기 위한 일반적인 단계입니다.
C#에서 CardElement라는 커스텀 요소 유형을 선언합니다.
UXML에서 커스텀 컨트롤의 계층 구조를 정의합니다. 두 가지 방식을 사용할 수 있습니다. 두 방식 모두 C# 및 부모 UXML에서의 CardElement 인스턴스화를 지원합니다.
커스텀 컨트롤의 자식 요소에 대한 레퍼런스를 찾습니다.
프로퍼티와 메서드를 노출하고 C# 클래스에서와 동일한 방식으로 커스텀 컨트롤에 로직을 캡슐화합니다.
커스텀 컨트롤을 게임 또는 애플리케이션 코드와 연결합니다. 사용자 상호 작용을 구현하기 위해 이벤트 콜백을 등록할 수도 있습니다.
이 방식을 사용하면 커스텀 요소 CardElement를 계층 구조 UXML 문서에 포함시키고 그 바로 아래에 자식 요소를 선언한 다음, 계층 구조 UXML 문서를 템플릿으로 사용합니다. 이 방식은 계층 구조 UXML 문서 내에 고정된 UI 구조를 포함하는 더 간단한 솔루션입니다.
다음 C# 및 UXML 예시에서는 UXML 우선 방식을 사용하여 재사용 가능한 UI를 생성하는 방법을 보여 줍니다.
CardElement 커스텀 컨트롤을 정의하는 C# 스크립트를 생성합니다. 커스텀 컨트롤 클래스는 CardElement에 이미지 및 배지 값을 할당합니다.
using UnityEngine;
using UnityEngine.UIElements;
// Define the custom control type.
[UxmlElement]
public partial class CardElement : VisualElement
{
private VisualElement portraitImage => this.Q("image");
private Label attackBadge => this.Q<Label>("attack-badge");
private Label healthBadge => this.Q<Label>("health-badge");
// Use the Init() approach instead of a constructor because
// we don't have children yet.
public void Init(Texture2D image, int health, int attack)
{
portraitImage.style.backgroundImage = image;
attackBadge.text = health;
healthBadge.text = attack;
}
// Custom controls need a default constructor.
public CardElement() {}
}
CardElement의 계층 구조를 정의하는 UXML 문서(CardElement.uxml)를 생성합니다. 이 예시에서는 CardElement의 스타일을 USS 파일로 지정합니다.
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<Style src="CardElementUI.uss" />
<CardElement>
<ui:VisualElement name="image" />
<ui:VisualElement name="stats">
<ui:Label name="attack-badge" class="badge" />
<ui:Label name="health-badge" class="badge" />
</ui:VisualElement>
</CardElement>
</ui:UXML>
다음을 통해 커스텀 컨트롤을 게임에 연결할 수 있습니다.
CardElement.uxml을 인스턴스화합니다. UI 빌더에서 계층 구조 UXML과 이 UXML 문서 간에 앞뒤로 이동할 수 있습니다.CardElement가 포함된 CardElement.uxml을 인스턴스화합니다. 씬에 추가하기 전에 UQuery를 사용하여 CardElement를 찾아야 합니다.씬에 커스텀 컨트롤을 추가한 후 Init()를 호출합니다.
또한 요소와 상호 작용하는 클릭 이벤트와 같은 게임플레이 관련 행동도 추가할 수 있습니다.
부모 UXML 내에 인스턴스화
다음은 UXML에서의 인스턴스화 예시입니다.
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:Template name="CardElement" src="CardElement.uxml"/>
<ui:Instance template="CardElement"/>
<ui:Instance template="CardElement"/>
<ui:Instance template="CardElement"/>
</ui:UXML>
게임에서 UXML 문서를 렌더링하는 방법에 대한 내용은 게임 뷰에서 UI 렌더링을 참조하십시오.
C#에서 직접 인스턴스화
참고: 이 페이지에 있는 학습 목적의 예시 코드는 편리하게 UXML 파일을 로드하기 위해 Resources 폴더 방식을 사용합니다. 하지만 이 방법은 잘 확장되지 않습니다. 프로덕션 프로젝트에 대한 레퍼런스를 로드하려면 다른 방법을 사용하는 것이 좋습니다.
다음은 C#에서의 인스턴스화 예시입니다.
using UnityEngine;
using UnityEngine.UIElements;
public class UIManager : MonoBehaviour
{
public void Start()
{
UIDocument document = GetComponent<UIDocument>();
// Load the UXML document that defines the hierarchy of CardElement.
// It assumes the UXML file is placed at the "Resources" folder.
VisualTreeAsset template = Resources.Load<VisualTreeAsset>("CardElement");
// Create a loop to modify properties and perform interactions
// for each card. It assumes that you have created a function
// called `GetCards()` to get all the cards in your game.
foreach(Card card in GetCards())
{
// Instantiate a template container.
var templateContainer = template.Instantiate();
// Find the custom element inside the template container.
var cardElement = templateContainer.Q<CardElement>();
// Add the custom element into the scene.
document.rootVisualElement.Add(cardElement);
// Initialize the card.
cardElement.Init(card.image, card.health, card.attack);
// Register an event callback for additional interaction.
cardElement.RegisterCallback<ClickEvent>(SomeInteraction);
}
}
private void SomeInteraction(ClickEvent evt)
{
// Interact with the elements here.
}
}
이 방식을 사용하면 계층 구조 UXML 문서에 자식 요소만 포함하고 C#을 사용하여 CardElement 클래스 정의에 계층 구조 UXML 문서를 로드할 수 있습니다. 이 방식은 커스텀 컨트롤을 위한 유연한 UI 구조를 제공합니다. 예를 들어 특정 조건에 따라 다른 계층 구조 UXML 문서를 로드할 수 있습니다.
다음 C# 및 UXML 예시에서는 요소 우선 방식을 사용하여 재사용 가능한 UI를 생성하는 방법을 보여 줍니다.
CardElement 커스텀 컨트롤을 정의하는 C# 스크립트를 생성합니다. 커스텀 컨트롤은 이미지 및 배지 값을 CardElement에 할당하는 생성자 정의 외에도 클래스 정의에서 계층 구조 UXML 문서를 로드합니다.
using UnityEngine;
using UnityEngine.UIElements;
// Define the custom control type.
[UxmlElement]
public partial class CardElement : VisualElement
{
private VisualElement portraitImage => this.Q("image");
private Label attackBadge => this.Q<Label>("attack-badge");
private Label healthBadge => this.Q<Label>("health-badge");
// Custom controls need a default constructor. This default constructor
// calls the other constructor in this class.
public CardElement() {}
// Define a constructor that loads the UXML document that defines
// the hierarchy of CardElement and assigns an image and badge values.
public CardElement(Texture2D image, int health, int attack)
{
// It assumes the UXML file is called "CardElement.uxml" and
// is placed at the "Resources" folder.
var asset = Resources.Load<VisualTreeAsset>("CardElement");
asset.CloneTree(this);
portraitImage.style.backgroundImage = image;
attackBadge.text = health.ToString();
healthBadge.text = attack.ToString();
}
}
참고: 성능에 문제가 있는 경우 지연 초기화를 사용해 필드를 유지하여 참조를 캐시하고 쿼리를 너무 자주 다시 평가하지 않도록 하십시오.
CardElement 자식 요소의 계층 구조를 정의하는 UXML 문서(CardElement.uxml)를 생성합니다. 이 예시에서는 CardElement의 스타일을 USS 파일로 지정합니다.
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<Style src="CardElementUI.uss" />
<ui:VisualElement name="image" />
<ui:VisualElement name="stats">
<ui:Label name="attack-badge" class="badge" />
<ui:Label name="health-badge" class="badge" />
</ui:VisualElement>
</ui:UXML>
다음을 수행하여 커스텀 컨트롤을 게임에 연결할 수 있습니다.
CardElement.uxml을 인스턴스화합니다. UI 빌더에서는 자식 요소가 C#에서 로드되기 때문에 계층 구조 UXML 간에 앞뒤로 이동할 수 없습니다.CardElement가 포함된 CardElement.uxml을 인스턴스화합니다.커스텀 컨트롤을 씬에 추가하기 전에 생성자를 호출합니다.
또한 요소와 상호 작용하는 클릭 이벤트와 같은 게임플레이 관련 행동도 추가할 수 있습니다.
부모 UXML 내에 인스턴스화
다음은 UXML에서의 인스턴스화 예시입니다.
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<CardElement />
<CardElement />
<CardElement />
</ui:UXML>
게임에서 UXML 문서를 렌더링하는 방법에 대한 내용은 게임 뷰에서 UI 렌더링을 참조하십시오.
C#에서 직접 인스턴스화
다음은 C#에서의 인스턴스화 예시입니다.
using UnityEngine;
using UnityEngine.UIElements;
public class UIManager : MonoBehaviour
{
public void Start()
{
UIDocument document = GetComponent<UIDocument>();
// Create a loop to modify properties and perform interactions
// for each card. It assumes that you have created a function
// called `GetCards()` to get all the cards in your game.
foreach(Card card in GetCards())
{
var cardElement = new CardElement(card.image, card.health, card.attack);
// Register an event callback for additional interaction.
cardElement.RegisterCallback<ClickEvent>(SomeInteraction);
// Add the custom element into the scene.
document.rootVisualElement.Add(cardElement);
}
}
private void SomeInteraction(ClickEvent evt)
{
// Interact with the elements here.
}
}
프로젝트의 UI가 복잡해질수록 로직을 고수준 컴포넌트로 분리하는 것이 좋습니다. 이렇게 하면 게임 또는 애플리케이션의 나머지 부분에 대해 UI를 더 쉽게 조정할 수 있습니다.
이 페이지의 개념을 적용하여 더 작고 일반적인 컴포넌트에서 점진적으로 특수 컴포넌트를 빌드할 수 있습니다. 예를 들어 사용자가 Options 메뉴와 About 섹션에 액세스할 수 있는 메인 타이틀 화면을 빌드하려면 3개의 다른 자식 UXML 문서를 사용하여 TitleScreenManager 요소를 생성하면 됩니다. 각각은 고유한 Title, Options, About 요소를 정의합니다.