Version: 2021.3
언어: 한국어
UXML을 통한 UI 구조
C# 스크립트에서 UXML 로드

UXML 템플릿 작성

UXML 템플릿은 사용자 인터페이스의 논리 구조를 정의하는 XML 마크업으로 작성된 텍스트 파일입니다. 다음 코드 예제는 사용자에게 선택을 요청하는 간단한 패널을 정의하는 방법을 보여줍니다.

<?xml version="1.0" encoding="utf-8"?>
<UXML
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="UnityEngine.UIElements"
    xsi:noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd"
    xsi:schemaLocation="UnityEngine.UIElements ../UIElementsSchema/UnityEngine.UIElements.xsd">

    <Label text="Select something to remove from your suitcase:"/>
    <Box>
        <Toggle name="boots" label="Boots" value="false" />
        <Toggle name="helmet" label="Helmet" value="false" />
        <Toggle name="cloak" label="Cloak of invisibility" value="false"/>
    </Box>
    <Box>
        <Button name="cancel" text="Cancel" />
        <Button name="ok" text="OK" />
    </Box>
</UXML>

파일의 첫 번째 줄은 XML 선언입니다. 이 선언은 선택 사항입니다. 이 선언을 포함할 경우 제일 첫 줄에 있어야 하며 다른 콘텐츠나 공백이 먼저 나올 수 없습니다. version 속성은 필수이지만 encoding 속성은 선택 사항입니다. encoding을 포함할 경우에는 파일의 캐릭터 인코딩을 선언해야 합니다.

다음 줄에 있는 <UXML>은 문서 루트를 정의합니다. <UXML> 요소는 네임스페이스 접두사 정의와 스키마 정의 파일의 위치에 대한 속성을 포함합니다. 이러한 속성에는 특별하게 지정된 순서가 없습니다.

UI 툴킷에서 각 요소는 UnityEngine.UIElements 또는 UnityEditor.UIElements 네임스페이스 중 하나로 정의됩니다.

  • UnityEngine.UIElements 네임스페이스에는 Unity 런타임의 일부로 정의되는 요소가 포함됩니다.
  • UnityEditor.UIElements 네임스페이스에는 Unity 에디터에서 이용 가능한 요소가 포함됩니다. 요소를 완전히 지정하려면 네임스페이스를 접두사로 사용해야 합니다.

예를 들어 UXML 템플릿에서 Button 요소를 사용하려면 <UnityEngine.UIElements:Button />을 지정해야 합니다.

네임스페이스를 더 쉽게 지정하기 위해 네임스페이스 접두사를 정의할 수 있습니다. 예를 들어 xmlns:engine="UnityEngine.UIElements"engine 접두사를 UnityEngine.UIElements로 정의합니다. 네임스페이스 접두사가 정의되면 이를 사용하여 네임스페이스를 지정할 수 있습니다. 예를 들어 <engine:Button /><UnityEngine.UIElements:Button />과 동일합니다.

또한 접두사를 제외하여 기본 네임스페이스를 정의할 수도 있습니다. 예를 들어 xmlns="UnityEngine.UIElements" 줄은 UnityEngine.UIElements를 기본 네임스페이스로 정의합니다. 즉, <Button />을 지정하는 것이 <UnityEngine.UIElements:Button />을 지정하는 것과 동일합니다.

고유한 요소를 정의하는 경우 해당 요소는 자체 네임스페이스로 정의될 수 있습니다. 이러한 요소는 UXML 템플릿에서 사용하려면 네임스페이스 정의와 스키마 파일 위치를 Unity 네임스페이스와 함께 <UXML> 태그에 포함해야 합니다.

Asset > Create > UI Toolkit > Editor Window를 선택하여 새로운 UXML 템플릿 에셋을 만들 경우 에디터는 네임스페이스를 자동으로 정의합니다.

UI 정의는 <UXML> 루트 내에 있습니다. UI 정의는 일련의 중첩된 XML 요소이며 각 요소는 VisualElement를 나타냅니다.

요소 이름은 인스턴스화할 요소의 C# 클래스 이름과 동일합니다. 대부분의 요소에는 속성이 포함되어 있고 각 값은 C#으로 해당 클래스 프로퍼티에 매핑됩니다. 각 요소는 해당 부모 클래스 타입(고유한 속성 집합을 추가할 수 있음)으로부터 속성을 상속받습니다. VisualElement는 모든 요소의 기본 클래스이며, 모든 요소에 대해 다음의 속성을 제공합니다.

  • name: 요소의 식별자. 고유한 이름을 사용해야 합니다.
  • picking-mode: Position으로 설정하여 마우스 이벤트에 응답하거나 Ignore로 설정하여 마우스 이벤트를 무시합니다.
  • focus-index:(사용되지 않음) tabIndexfocusable을 사용합니다.
  • tabindex: 현재 요소의 태빙 포지션을 정의하는 정수입니다.
  • focusable: 요소에 포커스를 둘 수 있는지 여부를 표시하는 부울입니다.
  • class: 요소를 특성화하는 식별자 목록으로, 공백으로 구분됩니다. 클래스를 사용하여 시각적 스타일을 요소에 할당하십시오. 클래스를 사용하여 UQuery에서 요소 집합을 선택할 수도 있습니다.
  • tooltip: 마우스 커서가 요소 위에 있을 때 툴팁으로 표시되는 문자열입니다.
  • view-data-key: 요소 직렬화에 사용되는 키를 정의하는 문자열입니다.

UXML 템플릿 예제에서는 사용자 인터페이스의 시각적 요소를 정의하지 않습니다. 스타일 정보(예: UI 그리기에 필요한 크기, 폰트, 컬러)는 별도의 USS 파일에서 정의하는 것이 좋습니다(스타일과 Unity 스타일시트 참조).

UXML에 스타일 추가

스타일시트 파일을 참조하기 위해 UXML 파일은 모든 요소 선언 아래의 <Style> 요소를 사용할 수 있습니다.

예를 들어 UXML 파일과 “styles.uss”라는 이름의 USS 파일이 동일 폴더에 있을 수 있습니다.

<engine:UXML ...>
    <engine:VisualElement class="root">
        <Style src="styles.uss" />
    </engine:VisualElement>
</engine:UXML>
# root {
    width: 200px;
    height: 200px;
    background-color: red;
}

참고: Unity는 루트 <UXML> 요소 아래의 <Style> 요소를 지원하지 않습니다.

또한 인라인 스타일을 UXML 요소의 속성으로 직접 선언할 수도 있습니다.

<engine:UXML ...>
    <engine:VisualElement style="width: 200px; height: 200px; background-color: red;" />
</engine:UXML>

UXML 파일 재사용

컴포넌트는 UXML 파일에서 정의하여 간단하게 생성할 수 있으며, <Template><Instance> 요소를 사용하여 다른 UXML 파일로 임포트할 수 있습니다.

대규모 사용자 인터페이스를 디자인하는 경우 UI 요소를 정의하는 템플릿 UXML 파일을 사용할 수 있습니다.

동일한 UI 정의를 여러 곳에서 사용할 수 있습니다. 예를 들어 이미지, 이름, 레이블이 포함된 세로 UI 요소를 가지고 있다고 가정해 보겠습니다. 이 경우 UXML 템플릿 파일을 생성하여 세로 UI 요소를 다른 UXML 파일에서 재사용할 수 있습니다.

예를 들어 Assets/Portrait.uxml 파일에 Portrait 컴포넌트가 있다고 가정해 보겠습니다.

<engine:UXML ...>
    <engine:VisualElement class="portrait">
        <engine:Image name="portaitImage" style="--unity-image: url(\"a.png\")"/>
        <engine:Label name="nameLabel" text="Name"/>
        <engine:Label name="levelLabel" text="42"/>
    </engine:VisualElement>
</engine:UXML>

다음과 같이 Portrait 컴포넌트를 다른 UXML 템플릿에 임베드할 수 있습니다.

<engine:UXML ...>
    <engine:Template src="/Assets/Portrait.uxml" name="Portrait"/>
    <engine:VisualElement name="players">
        <engine:Instance template="Portrait" name="player1"/>
        <engine:Instance template="Portrait" name="player2"/>
    </engine:VisualElement>
</engine:UXML>

UXML 속성 오버라이드

UXML 템플릿의 인스턴스를 생성할 때 해당 요소의 기본 속성 값을 오버라이드할 수 있습니다. 속성 오버라이드를 사용하면 각 인스턴스에 대해 다른 값으로 동일한 템플릿을 여러 번 인스턴스화할 수 있습니다.

속성을 오버라이드하려면 다음을 지정해야 합니다.

  • 속성을 오버라이드하려는 요소의 element-name attribute
  • 오버라이드하려는 속성의 이름
  • 새로운 속성 값

다음 예제에서 다음을 참고하십시오.

  • player-name-label은 요소의 element-name 속성입니다.
  • text는 오버라이드의 속성입니다.
  • Alice는 새로운 속성 값입니다.
<AttributeOverrides element-name="player-name-label" text="Alice" />

속성 오버라이드는 전체 인스턴스에 영향을 미치므로, 인스턴스에 player-name-label이라는 두 개의 요소가 있고 둘 다에 text 속성이 있는 경우 오버라이드는 두 요소 모두에 영향을 줍니다.

속성 오버라이드 예시

게임을 만들고 있고, 각 플레이어에 대한 동일한 정보 세트를 표시한다고 가정해보겠습니다. 이 경우 단일 재사용 가능 템플릿을 생성하고, 속성 오버라이드를 사용하여 플레이어별 인스턴스를 생성할 수 있습니다.

예를 들어 다음의 템플릿을 생성할 수 있습니다.

    <UXML xmlns="UnityEngine.UIElements">
            <Label name="player-name-label" text="default name" />
            <Label name="player-score-label" text="default score" />
        </UXML>

다른 UXML 파일에서 인스턴스화하고 해당 속성을 오버라이드하여 각 플레이어의 이름과 점수를 표시할 수 있습니다.

    <UXML xmlns="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
            <Template src="MyTemplate.uxml" name="MyTemplate" />
            <Instance name="player1" template="MyTemplate">
                <AttributeOverrides element-name="player-name-label" text="Alice" />
                <AttributeOverrides element-name="player-score-label" text="2" />
            </Instance>
            <Instance name="player2" template="MyTemplate">
                <AttributeOverrides element-name="player-name-label" text="Bob" />
                <AttributeOverrides element-name="player-score-label" text="1" />
            </Instance>
        </UXML>

여러 속성 오버라이드

오버라이드당 두 개 이상의 속성을 지정할 수 있습니다. 예를 들어 다음 구문은 player-name-label이라는 인스턴스에서 요소를 찾아 다음을 수행합니다.

  • text 속성의 기본값을 새로운 값 Alice로 오버라이드합니다.
  • tooltip 속성의 기본값을 새로운 값 Tooltip 1로 오버라이드합니다.
<AttributeOverrides element-name="player-name-label" text="Alice" tooltip="Tooltip 1" />

중첩 속성 오버라이드

속성 오버라이드는 요소 계층 구조에서 중첩된 템플릿을 통해 전파됩니다. 예를 들어 템플릿 A는 템플릿 B를 인스턴스화하고, 템플릿 B는 템플릿 C를 인스턴스화하는 경우 템플릿 A와 템플릿 B는 둘 다 템플릿 C의 속성을 오버라이드할 수 있습니다.

중첩된 템플릿에서 속성을 오버라이드하면 가장 깊은 오버라이드가 우선권을 갖습니다. 따라서 위 예제에서 템플릿 A와 템플릿 B가 둘 다 템플릿 C의 동일한 속성을 오버라이드하는 경우 템플릿 B의 오버라이드는 렌더링된 UI에 실제로 표시되는 요소를 결정합니다.

제한 사항

  • 속성 오버라이드는 지정된 요소 이름에 따라 매칭되는 속성을 찾습니다. 요소 매칭을 위해 USS 선택자 또는 UQUery는 사용하지 않습니다.
  • 요소의 binding-path 속성을 오버라이드할 수 있지만, 속성 오버라이드는 데이터 바인딩과 연결되지 않습니다.
  • 요소의 name 또는 style 속성을 오버라이드할 수 없습니다.

UXML의 기타 파일 레퍼런스

UXML 파일은 요소를 통해 다른 UXML 파일과 USS 파일을 참조할 수 있습니다.

<Template> 요소와 <Style> 요소는 모두 “src” 속성 또는 “path” 속성을 허용합니다.

src 속성은 상대 경로를 허용하고, 임포트 시점에 오류 메시지를 제공하고(예: 파일이 누락된 경우), Unity가 플레이어 빌드에서 UXML 파일이 참조하는 에셋을 올바르게 포함하도록 합니다.

path 속성은 Unity 리소스 메커니즘의 사용을 허용하지만, 임포트 시점에 오류 보고를 제공하지 않고 상대 경로도 허용하지 않습니다.

src 속성

src 속성은 파일 경로가 프로젝트 루트 또는 UXML 파일이 담긴 폴더와 관련된다고 예상합니다. 파일 확장자는 반드시 포함해야 합니다. 다음 예제에서 UXML 파일은 _Assets\Editor\UXML 에 있고 thumb.png USS 파일은 Assets\Editor\USS 에 있습니다.

  • UXML 파일의 위치에 따라 다음 예제 경로 중 하나를 사용하십시오. src="../USS/styles.uss" 또는 src="template.uxml"
  • 프로젝트의 위치에 따라 다음 예제 중 하나를 절대 경로에 사용하십시오. src="/Assets/Editor/USS/styles.uss" 또는 src="project:/Assets/Editor/UXML/template.uxml"

path 속성

path 속성은 Resources 폴더 또는 Editor Default Resources 폴더에 있는 파일을 허용합니다. 단, 다음 규칙을 따르십시오.

  • 파일이 Resources 폴더에 있으면 파일 확장자를 포함하지 마십시오. 예를 들어 Assets/Resources/template.uxml 에 있는 파일의 경우 path="template"이라고 작성하십시오.
  • 파일이 Editor Default Resources 폴더에 있으면 파일 확장자를 반드시 포함해야 합니다. 예를 들어 Assets/Editor Default Resources/template.uxml 에 있는 파일의 경우 path="template.uxml"이라고 작성하십시오.
UXML을 통한 UI 구조
C# 스크립트에서 UXML 로드