UXML 파일은 사용자 인터페이스의 논리 구조를 정의하는 텍스트 파일입니다. 이 UXML 파일에서 사용되는 포맷은 HTML(HyperText Markup Language), XAML(eXtensible Application Markup Language), XML(eXtensible Markup Language)의 영감을 받았습니다. 이러한 잘 알려진 포맷에 익숙하다면 UXML에서 많은 공통점을 찾아볼 수 있습니다. 하지만 UXML 포맷에는 Unity 작업의 효율을 높여주는 작은 차이점들이 있습니다.
이 섹션에서는 Unity에서 지원하는 UXML 포맷을 설명하고, UXML 템플릿을 작성, 로드 및 정의하는 방법에 대한 상세 정보를 제공합니다. 또한 새로운 요소를 정의하고 UQuery를 정의하는 방법도 함께 소개합니다.
UXML은 기술 숙련도가 낮은 사용자들이 Unity로 사용자 인터페이스를 쉽게 빌드하도록 도와줍니다. UXML은 다음의 기능을 제공합니다.
이 경우 개발자들이 에셋 임포트, 로직 정의 및 데이터 처리 같은 기술 작업을 직접 수행해야 합니다.
UIElements는 확장이 가능하므로 개발자들은 고유한 사용자 인터페이스 컴포넌트와 요소를 정의할 수 있습니다.
UXML 파일을 사용하여 새로운 요소를 정의하기 전에 VisualElement
또는 해당 서브 클래스 중 하나에서 새로운 클래스를 파생한 후 새로운 클래스 안에 적절한 기능을 구현해야 합니다. 새로운 클래스는 반드시 기본 생성자를 구현해야 합니다.
예를 들어, 다음 코드는 새로운 StatusBar
클래스를 파생하고 해당 기본 생성자를 구현합니다.
class StatusBar : VisualElement
{
public StatusBar()
{
m_Status = String.Empty;
}
string m_Status;
public string status { get; }
}
UXML 파일을 읽을 때 UIElements가 새로운 클래스를 인스턴스화할 수 있도록 만들려면 클래스에 대해 팩토리를 정의해야 합니다. 팩토리가 특별한 작업을 할 필요가 없는 경우에는 UxmlFactoy<T>
에서 팩토리를 파생할 수 있습니다. 또한 팩토리 클래스는 컴포넌트 클래스 안에 배치하는 것이 좋습니다.
예를 들어 다음 코드는 UxmlFactory<T>
에서 StatusBar
클래스의 팩토리를 파생하여 해당 클래스에 대한 팩토리를 정의하는 방법을 보여줍니다. 팩토리에는 Factory
라는 이름이 지정됩니다.
class StatusBar : VisualElement
{
public new class Factory : UxmlFactory<StatusBar> {}
// ...
}
이 팩토리를 정의하고 나면 UXML 파일에서 <StatusBar>
요소를 사용할 수 있습니다.
참고: 팩토리는 2018.2에서 개선되었습니다. 이전 버전에서 팩토리를 정의했다면 현재는 지원이 중단된 API를 사용하지 않도록 해당 팩토리를 2018.3으로 이식해야 합니다.
새로운 클래스에 대해 UXML 특성을 정의하고 해당 팩토리가 그러한 특성을 사용하도록 설정할 수 있습니다.
예를 들어 다음 코드는 UXML 특성 클래스를 정의하여 status
프로퍼티를 StatusBar
클래스의 프로퍼티로 초기화하는 방법을 보여줍니다. 상태 프로퍼티는 XML 데이터에서 초기화됩니다.
class StatusBar : VisualElement
{
public new class Factory : UxmlFactory<StatusBar, UxmlTraits> {}
public new class Traits : base.UxmlTraits
{
UxmlStringAttributeDescription m_Status = new UxmlStringAttributeDescription { name = "status" };
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
get { yield break; }
}
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
base.Init(ve, bag, cc);
((StatusBar)ve).status = m_Status.GetValueFromBag(bag, cc);
}
}
// ...
}
UxmlTraits
는 다음의 두 가지 역할을 수행합니다.
팩토리가 새로 생성된 오브젝트를 초기화하는 데 사용합니다.
스키마 생성 프로세스가 요소에 대한 정보를 가져오기 위해 분석합니다. 이 정보는 XML 스키마 지시문으로 변환됩니다.
위 코드 예제는 다음을 수행합니다.
m_Status
선언은 status
라는 이름의 XML 속성을 정의합니다.uxmlChildElementsDescription
은 StatusBar
요소에 자식이 없음을 의미하는 빈 IEnumerable
을 반환합니다.Init()
멤버는 XML 파서의 프로퍼티 백에 있는 status
속성의 값을 읽은 후 StatusBar.status
프로퍼티를 이 값으로 설정합니다.UxmlTraits
클래스를 StatusBar
클래스 내부에 배치하여 Init()
메서드가 StatusBar
의 프라이빗 멤버에 액세스하도록 허용합니다.UxmlTraits
클래스는 UxmlTraits
기본 클래스에서 상속되기 때문에 기본 클래스의 속성을 공유합니다.Init()
은 base.Init()
를 호출하여 기본 클래스 프로퍼티를 초기화합니다.위 코드 예제는 UxmlStringAttributeDescription
클래스로 문자열 속성을 선언합니다. UIElements는 다음 타입의 속성을 지원하며 각각 C# 타입을 XML 타입에 연결합니다.
UxmlStringAttributeDescription
: 속성 값은 문자열입니다.UxmlFloatAttributeDescription
: 속성 값은 C# float
타입의 범위 내에 있는 하나의 정밀도 부동 소수점 값이어야 합니다.UxmlDoubleAttributeDescription
: 속성 값은 C# double
타입의 범위 내에 있는 이중 정밀도 부동 소수점 값이어야 합니다.UxmlIntAttributeDescription
: 속성 값은 C# int
타입의 범위 내에 있는 정수 값이어야 합니다.UxmlLongAttributeDescription
: 속성 값은 C# long
타입의 범위 내에 있는 긴 정수 값이어야 합니다.UxmlBoolAttributeDescription
: 속성 값은 true
또는 false
여야 합니다.UxmlColorAttributeDescription
: 속성 값은 컬러를 나타내는 문자열(#FFFFFF
)이어야 합니다.UxmlEnumAttributeDescription<T>
속성 값은 Enum
타입 T
에 대한 값 중 하나를 나타내는 문자열이어야 합니다.위 코드 예제에서 uxmlChildElementsDescription
은 빈 IEnumerable
을 반환하며, 이는 StatusBar
요소가 자식을 허용하지 않음을 의미합니다.
요소가 모든 타입의 자식을 허용하도록 만들려면 uxmlChildElementsDescription
프로퍼티를 오버라이드해야 합니다. 예를 들어 StatusBar
요소가 모든 타입의 자식을 허용하려면 uxmlChildElementsDescription
프로퍼티를 다음과 같이 지정해야 합니다.
public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
get
{
yield return new UxmlChildElementDescription(typeof(VisualElement));
}
}
C#으로 새 요소를 정의하고 나면 UXML 파일에서 해당 요소를 사용할 수 있습니다. 새 요소가 새로운 네임스페이스로 정의된 경우 해당 네임스페이스에 대한 접두사를 정의해야 합니다. 네임스페이스 접두사는 속성으로 루트 <UXML>
요소에 대해 선언되고, 요소 범위 지정 시 전체 네임스페이스 이름을 대체합니다.
네임스페이스 접두사를 정의하려면 UxmlNamespacePrefix` 속성을 정의하려는 각 네임스페이스 접두사의 어셈블리에 추가하십시오.
[assembly: UxmlNamespacePrefix("My.First.Namespace", "first")]
[assembly: UxmlNamespacePrefix("My.Second.Namespace", "second")]
이 작업은 어셈블리 C# 파일의 루트 수준(모든 네임스페이스 외부)에서 수행할 수 있습니다.
이 스키마 생성 시스템은 다음을 수행합니다.
<UXML>
요소의 속성으로 추가합니다.xsi:schemaLocation
속성의 네임스페이스에 대한 스키마 파일 위치를 포함합니다.프로젝트의 UXML 스키마를 업데이트해야 합니다. Assets > Update UIElements Schema를 선택하여 텍스트 편집기가 새 요소를 인식하는지 확인하십시오.
IUxmlFactory.uxmlName
및 IUXmlFactory.uxmlQualifiedName
프로퍼티를 오버라이드하여 UXML 이름을 커스터마이즈할 수 있습니다. uxmlName
이 네임스페이스 내에서 고유한 이름이고, uxmlQualifiedName
이 프로젝트 내에서 고유한 이름이어야 합니다.
두 이름 모두가 고유하지 않으면 어셈블리를 로드하려고 할 때 예외가 발생합니다.
다음 코드 예제는 UXML 이름을 오버라이드하고 커스터마이즈하는 방법을 보여줍니다.
public class FactoryWithCustomName : UxmlFactory<..., ...>
{
public override string uxmlName
{
get { return "UniqueName"; }
}
public override string uxmlQualifiedName
{
get { return uxmlNamespace + "." + uxmlName; }
}
}
기본적으로 IUxmlFactory
는 요소를 인스턴스화하고, 요소 이름을 사용하여 요소를 선택합니다.
IUXmlFactory.AcceptsAttributeBag
을 오버라이드하여 선택 프로세스가 요소의 속성 값을 고려하도록 만들 수 있습니다. 그러면 팩토리는 요소 속성을 검사하여 UXML 요소의 오브젝트를 인스턴스화할 수 있는지 결정합니다.
이는 VisualElement
클래스가 일반인 경우에 특히 유용합니다. 이 경우 클래스의 전문화를 위한 클래스 팩토리가 XML type
속성의 값을 검사할 수 있습니다. 해당 값에 따라 인스턴스화가 허용되거나 거절될 수 있습니다. 예제는 PropertyControl<T>
구현을 참조하십시오.
두 개 이상의 팩토리가 요소를 인스턴스화할 수 있는 경우에는 첫 번째로 등록된 팩토리가 선택됩니다.
파생된 UxmlTraits
클래스에서 defaultValue
를 설정하여 기본 클래스에서 선언된 속성의 기본 값을 변경할 수 있습니다.
예를 들어 다음 코드는 m_focusIndex
의 기본 값을 변경하는 방법을 보여줍니다.
class MyElementTraits : VisualElementUxmlTraits
{
public Traits()
{
m_focusIndex.defaultValue = 0;
}
}
기본적으로 생성된 XML 스키마는 요소가 모든 속성을 가질 수 있다고 명시합니다.
UxmlTraits
클래스에서 선언된 속성을 제외한 속성 값은 제한되지 않습니다. 이는 선언된 속성의 값이 해당 선언과 일치하는지 확인하는 XML 검증기와 대조됩니다.
추가 속성을 IUxmlAttributes
백에 포함하여 IUxmlFactory.AcceptsAttributBag()
및 IUxmlFactory.Init()
함수에 전달할 수 있습니다. 이러한 추가 속성의 사용 여부는 팩토리 구현에 따라 달라집니다. 기본 동작은 추가 속성을 버리는 것입니다.
즉, 이러한 추가 속성들은 인스턴스화된 VisualElement
에 연결되지 않으며 UQuery
를 사용하여 쿼리할 수 없습니다.
새 요소를 정의할 때 UxmlTraits
생성자에서 UxmlTraits.canHaveAnyAttribute
프로퍼티를 false
로 설정하여 허용되는 속성을 명시적으로 선언된 속성으로만 제한할 수 있습니다.
스키마 정의 파일은 속성, 그리고 각 UXML 요소가 포함할 수 있는 자식 요소를 지정합니다. 스키마 정의 파일을 가이드로 사용하여 올바른 문서를 작성하고 문서의 유효성을 확인하십시오.
UXML 템플릿 파일에서 <UXML>
루트 요소의 xsi:noNamespaceSchemaLocation
및 xsi:schemaLocation
속성은 스키마 정의 파일의 위치를 지정합니다.
Assets > Create > UIElements View 메뉴 항목을 선택하여 프로젝트에서 사용하는 VisualElement
서브 클래스에서 얻은 최신 정보로 스키마 정의를 자동으로 업데이트하십시오. UXML 스키마 파일을 강제로 업데이트하려면 Assets > Update UIElements Schema를 선택하십시오.
참고: 일부 텍스트 편집기는 xsi:noNamespaceSchemaLocation
속성을 인식하지 않습니다. 텍스트 편집기가 스키마 정의 파일을 찾지 못하면 xsi:schemaLocation
속성도 지정해 주어야 합니다.