일반적으로 UI 개발자는 백엔드 데이터와 시각 디자인을 별개의 시스템으로 나눕니다. 이렇게 하면 UI를 구축하는 프로세스가 변경사항으로 인한 영향을 덜 받게 됩니다. 디자이너는 UI 이면의 코드를 변경하는 일 없이 시각적 프레젠테이션을 변경할 수 있고 프로그래머는 프런트엔드가 완료되기를 기다릴 필요 없이 데이터와 시스템에 집중할 수 있기 때문입니다. 뷰모델(View Model) 플러그인은 뷰모델 에셋과 뷰 바인딩을 도입하여 이 워크플로에 매개체를 제공합니다.
워크플로
뷰 모델은 UI에서 사용할 수 있는 변수를 포함합니다. 디자이너는 뷰 바인딩(View Binding) 패널을 사용하여 UI에서 이러한 변수에 필드를 바인딩할 수 있으며, 프로그래머는 뷰모델 자체를 빌드하고 애플리케이션의 코드와 결합하여 적절한지 살펴볼 수 있습니다.
UMG 위젯에 뷰모델을 추가하면 해당 뷰모델에 액세스하여 함수를 호출하거나 변수를 업데이트할 수 있습니다. 뷰 모델은 필드가 해당 변수에 바인딩된 위젯에 업데이트를 푸시할 수 있습니다.
이는 변수를 업데이트할 때 위젯만 업데이트하기 때문에 원시 어트리뷰트 바인딩보다 효과적인 대한 역할을 합니다. 또한 시간 설정을 수동으로 구현할 필요가 없으므로 이벤트 기반 UI 프레임워크의 이점을 실현할 수 있습니다.
필수 설정
프로젝트의 UI에서 뷰모델을 사용하려면 플러그인(Plugins) 메뉴에서 UMG 뷰모델(UMG Viewmodel) 플러그인을 활성화해야 합니다.
이 플러그인을 활성화하지 않으면 UMVVMViewModelBase 클래스를 사용할 수 없으며 UMG에서 뷰 바인딩을 사용할 수 없습니다.
뷰 모델
뷰 모델은 다음과 같은 두 가지 목적을 가집니다.
UI에 필요한 변수의 매니페스트를 관리합니다.
UI와 애플리케이션의 나머지 요소 간의 커뮤니케이션을 위한 매개체를 제공합니다.
UI가 변수를 인지해야 하는 경우, 뷰 모델에 변수를 추가한 다음 뷰 모델을 위젯에 추가하여 필드를 바인딩할 수 있습니다. 변수를 업데이트해야 하는 경우, 뷰 모델에 대한 레퍼런스를 구하고 여기에서 바로 설정할 수 있습니다. 그런 다음 변경사항과 관련된 변수에 바인딩된 위젯을 노티파이하고 업데이트합니다.
블루프린트에서 뷰모델 생성
블루프린트에서 MVVMViewModelBase 클래스를 확장하여 뷰모델을 생성할 수 있습니다.
또한 C++에서 INotifyFieldValueChanged 인터페이스를 구현하여 뷰모델을 생성할 수 있습니다.
블루프린트에서의 뷰모델 변수
파라미터에 바인딩된 위젯에 변경사항을 브로드캐스트하려면 변수 또는 함수를 FieldNotify로 마킹해야 합니다. 함수 또는 변수를 FieldNotify로 만들려면 옆에 있는 종 모양의 아이콘을 클릭하세요.
FieldNotify 변수에 설정된 모든 호출은 일반적인 Set 노드가 아닌 Set W/Broadcast로 라벨이 지정되어 있습니다.
이러한 변수는 게임플레이 코드에서 새 값으로 설정될 때마다 해당 변수에 바인딩된 모든 위젯에 업데이트하라는 메시지를 전송합니다.
블루프린트에서의 뷰모델 함수
함수 역시 FieldNotifies로 취급될 수 있습니다. 함수를 FieldNotify로 사용하려면 반드시 다음과 같은 조건을 만족해야 합니다.
pure 함수여야 합니다.
Const로 마킹되어 있어야 합니다.
하나의 값만 반환해야 합니다.
입력 변수를 취해서는 안 됩니다.
예를 들어 캐릭터의 현재 체력 대비 최대 체력의 퍼센티지를 반환하는 Getter 함수를 생성할 수 있습니다. 캐릭터의 체력을 퍼센티지로 보유하는 변수를 별도로 생성하지 않으려는 경우 좋은 대안이 될 수 있습니다.
FieldNotify 변수가 변경되는 경우에는 이 변수에서 FieldNotify 함수를 트리거해야 합니다. 자세한 내용은 FieldNotify 변수를 사용하여 다른 FieldNotify 트리거하기를 참고하세요.
뷰모델 내에서 Getter 및 Setter 유틸리티 함수는 다른 연산을 수행하고 파생된 값을 처리할 수 있습니다. 예를 들어 플레이어의 체력을 트래킹하는 뷰모델이 있는 경우, 게임플레이 로직에서 이를 플로트로 처리하더라도 텍스트에서는 인티저로 표시해야 할 수 있으며, ProgressBar 위젯에서 사용하는 경우에는 퍼센티지로 변환해야 할 수 있습니다.
SetCurrentHealth 함수는 다른 FieldNotify 변수 내에서 파생된 값을 설정하거나 게임에서 필요할 수 있는 다른 로직을 수행할 수 있게 해줍니다.
FieldNotify 변수의 값을 반환하기 위해 Getter 함수를 생성하면 안 됩니다. FieldNotify 변수의 값을 직접 구하는 것만으로도 충분하며, 나중에 뷰모델 변수를 위젯에 바인딩하려고 할 때 추가 Getter 함수가 혼동을 줄 수 있기 때문입니다. 하지만 해당 정보를 저장할 변수를 추가로 만들지 않고도 스트링과 같은 필요한 포맷으로 변환하는 작업을 처리하는 데는 FieldNotify Getter를 사용할 수 있습니다.
FieldNotify 변수를 사용하여 다른 FieldNotify 트리거하기
FieldNotify 변수는 변경 시 다른 FieldNotify 함수를 자동으로 브로드캐스트할 수 있습니다. 이를 구성하려면 다음 단계를 따릅니다.
'변수(Variables)' 패널에서 사용할 FieldNotify 변수를 클릭합니다.
'디테일(Details)' 패널에서 '필드 노티파이(Field Notify)' 체크박스 옆의 드롭다운을 클릭합니다. 이렇게 하면 이 변수로 트리거할 수 있는 유효한 FieldNotify가 모두 표시되며, 여기에는 다른 변수 및 함수에 대한 FieldNotify도 포함됩니다.
이 변수가 변경될 때 트리거할 각 FieldNotify 박스를 체크합니다.
이제 타깃 변수를 변경하면 타깃 변수 자체에 대한 함수 외에도 여기에 연결된 모든 FieldNotify 함수가 트리거됩니다. 이 방법은 변수를 추가로 사용하는 것과 비교하여 파생된 값을 처리하는 작업을 더 간편하게 해줍니다.
C++에서 뷰모델 생성
INotifyFieldValueChanged 인터페이스를 구현하여 C++에서 뷰모델을 생성할 수 있습니다. 또한 기본적으로 이를 구현하는 UMVVMViewModelBase 클래스를 확장할 수도 있습니다. 뷰모델은 FieldNotify 변수와 함수에 바인딩된 위젯에 변경사항을 브로드캐스트하는 함수를 기반으로 하는 UObjects입니다.
블루프린트에서와 달리 C++에서는 FieldNotify 브로드캐스트를 수동으로 호출해야 합니다.
뷰모델 시스템은 블루프린트와 동일한 액세스 권한을 사용합니다. 뷰모델 시스템에서 변수와 함수에 액세스하려면 블루프린트에서도 액세스할 수 있어야 합니다.
FieldNotify와 변수
뷰모델에서 변수를 정의할 때는 각 변수가 FieldNotify 지정자를 갖춘 UPROPERTY 매크로가 있어야 합니다. FieldNotify 변수에 사용되는 지정자의 전체 목록은 다음과 같습니다.
| UPROPERTY 지정자 | Description |
|---|---|
| 필드 알림 브로드캐스트 시스템에서 프로퍼티를 사용할 수 있도록 합니다. |
| 변수가 값 설정을 허용해야 함을 나타냅니다. Setter 함수가 |
| Setter로 사용할 커스텀 함수의 이름을 제공할 수 있습니다. |
| 변수가 값 얻기를 허용해야 함을 나타냅니다. Getter 함수가 |
| Getter로 사용할 커스텀 함수의 이름을 제공할 수 있습니다. |
FieldNotify 지정자는 위젯에 값 변경사항을 브로드캐스트해야 합니다. 이 지정자를 가진 변수는 '뷰 바인딩' 메뉴에 표시됩니다. FieldNotify가 없는 경우 OneTime 모드에서만 변수에 바인딩할 수 있습니다.
Setter 또는 Getter 지정자를 제공할지 여부는 사용자가 결정할 수 있습니다. 두 지정자 중 하나를 제공하지 않기로 결정할 경우, 이 클래스 외부에서는 연산을 수행할 수 없습니다. 변수 자체를 위한 알림을 트리거하려는 경우에는 함수 이름 없이 Getter 및 Setter 지정자만 지정하면 됩니다. 이것은 변수에 액세스할 때 스크립트(블루프린트, 뷰모델, 시퀀서 등)에서 자동으로 실행됩니다. cpp 코드에서는 자동으로 호출되지 않습니다.
커스텀 Getter 및 Setter는 다음과 같은 경우에 유용합니다.
변수를 얻기 전에 연산을 수행해야 하는 경우
다른 함수를 트리거하려고 하거나 변수를 설정할 때 다른 변수를 업데이트하려는 경우
커스텀 Getter 또는 Setter 함수를 생성하는 경우 이러한 함수를 UFUNCTIONS로 만들면 블루프린트에서 Get 함수와 Set 함수에 대해 상당히 많은 목록이 생성되므로 피해야 합니다. 해당 변수의 UPROPERTY 매크로는 변수의 Get 노드와 Set 노드 형태로 이에 대한 액세스를 이미 제공합니다. 커스텀 Getter const 함수 또한 만들어야 하며, 해당 함수의 유일한 목적은 값을 반환하는 것입니다.
C++는 사용자가 Getter 또는 Setter 함수를 호출하도록 강제하지 않기 때문에, 사용자가 실수하는 것을 방지하려면 이 변수는 protected 또는 private이어야 합니다.
protected:
/**
* The variable can be accessed from the viewmodel system and can be written to. Enable TwoWay.
* FieldNotify enabled the OneWay binding mode (enable notification).
* It's protected in cpp (force the user to use the Getter/Setter).
* It's public in Blueprint
* Blueprint/ViewBindings/... will use the Getter/Setter.
*/
FieldNotify와 함수
FieldNotify를 브로드캐스트하는 커스텀 함수를 생성할 수 있으며, 변수와 동일한 방식으로 위젯의 프로퍼티를 이러한 함수에 바인딩할 수 있습니다. 이런 방식으로 사용되는 함수는 다음의 요구 사항을 따라야 합니다.
FieldNotify및BlueprintPure지정자에UFUNCTION매크로가 있어야 합니다.실행인자를 추하지 않아야 합니다.
const함수여야 합니다.단일 값만 반환해야 합니다(out 실행인자 없음).
액세스 가능해야 합니다.
함수는 위젯을 다른 변수에서 파생되었거나 변환된 값에 바인딩하려고 하지만 해당 정보를 보유할 변수를 추가로 생성하는 것을 원하지 않는 경우에 유용합니다.
예를 들어 다음 함수는 캐릭터의 최대 체력으로 나눈 현재 체력의 퍼센트 값을 반환하기 위한 FieldNotify입니다.
UFUNCTION(BlueprintPure, FieldNotify)
float GetHealthPercent() const
{
//Check to avoid dividing by zero
if (MaxHealth != 0)
{
return (float) CurrentHealth / (float) MaxHealth;
}
CurrentHealth 또는 MaxHealth 변경 시 GetHealthPercent가 변경되었음을 수동으로 알려야 합니다.
매크로로 FieldNotify 트리거하기
변수를 변경할 때는 함수가 뷰 모델 알림 매크로 중 하나를 호출하여 바인딩된 위젯에 변경사항을 브로드캐스트해야 합니다. 사용 가능한 매크로의 목록은 다음과 같습니다.
| 뷰모델 매크로 | Description |
|---|---|
UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED([Member name]) | 이벤트를 브로드캐스트합니다. |
UE_MVVM_SET_PROPERTY_VALUE([Member Name], [New Value]) | 필드의 값이 변경되었는지 테스트한 다음 필드의 새 값을 설정하고 이벤트를 브로드캐스트합니다. |
매크로는 값을 할당하고 브로드캐스트하기 전에 값이 변경되었는지 확인한다는 점을 제외하고는 SET_PROPERTY_VALUEBROADCAST_FIELD_VALUE 매크로와 동일한 역할을 합니다. 이 확인 작업은 뷰 모델을 위한 Setter를 생성할 때 일반적으로 수행되는 것으로, 편의를 위해 포함되어 있습니다.
값에 직접 바인딩된 위젯을 노티파이하거나 함수의 이름을 취할 수 있는 경우, BROADCAST_FIELD_VALUE_CHANGED 매크로는 변수 자체를 취할 수 있습니다.
예시
다음 코드 스니펫은 위의 개념을 사용하는 뷰 모델 클래스의 예시입니다. GetHealthPercent는 Getter와 Setter에서 별도의 함수로 정의되어 있지만 변수가 변경될 때 노티파이하기 위해 Setter가 이를 호출합니다.
UCLASS(BlueprintType)
class UVMCharacterHealth : public UMVVMViewModelBase
{
GENERATED_BODY()
private:
UPROPERTY(BlueprintReadWrite, FieldNotify, Setter, Getter, meta=(AllowPrivateAccess))
int32 CurrentHealth;
UPROPERTY(BlueprintReadWrite, FieldNotify, Setter, Getter, meta=(AllowPrivateAccess))
위젯에 뷰 모델 추가하기
UMG의 '뷰 모델' 창에서 위젯에 뷰 모델을 추가할 수 있습니다. 이 창은 UMG 디자이너(UMG Designer) 탭의 창(Window) > 뷰모델(Viewmodels)에서 찾을 수 있습니다.
+ 뷰모델(+ Viewmodel) 버튼을 클릭하여 프로젝트의 뷰모델 중 하나를 선택한 다음 선택(Select)을 클릭합니다.
뷰 모델 초기화하기
뷰모델 창에서 뷰모델을 클릭할 때, 생성 타입(Creation Type) 세팅으로 뷰모델을 초기화하는 방법을 선택할 수 있습니다. 다음과 같은 방식을 사용할 수 있습니다.
| 뷰모델 생성 타입 | Description |
|---|---|
인스턴스 생성(Create Instance) | 위젯은 뷰 모델의 인스턴스를 자동으로 생성합니다. |
수동(Manual) | 위젯은 뷰모델을 Null로 초기화하기 때문에 인스턴스를 수동으로 생성한 다음 할당해야 합니다. |
글로벌 뷰모델 컬렉션(Global Viewmodel Collection) | 프로젝트에서 위젯에 의해 사용될 수 있는 글로벌로 사용 가능한 뷰 모델을 참고합니다. 글로벌 뷰모델 식별자가 필요합니다. |
프로퍼티 경로(Property Path) | 초기화 시 함수를 실행하여 뷰 모델을 찾습니다. 뷰모델 프로퍼티 경로는 마침표로 구분된 멤버 이름을 사용합니다. 예를 들어 GetPlayerController.Vehicle.ViewModel과 같습니다. 프로퍼티 경로는 언제나 위젯에 대해 상대적입니다. |
뷰 모델은 반드시 위젯과 일대일 관계를 가지는 것은 아닙니다. 뷰 모델을 구성하고 위젯에 할당하는 방법에는 여러 가지가 있으며 다수의 위젯이 단일 뷰 모델에서 정보를 취할 수 있습니다. 각 생성 타입 방식은 아래에 자세히 설명되어 있습니다.
인스턴스 생성
인스턴스 생성 생성 방식은 위젯의 고유한 각 인스턴스마다 뷰모델의 새로운 인스턴스를 자동으로 생성합니다. 즉, '뷰포트(Viewport)'에 동일한 위젯의 복제본이 여러 개 있고 그 중 하나의 뷰 모델 변수를 변경하면 다른 모든 사본은 동일하게 유지되지만 해당 위젯은 업데이트됩니다. 이와 유사하게, 동일한 뷰모델을 사용하는 여러 개의 서로 다른 위젯을 생성하는 경우 이러한 위젯은 다른 위젯의 정보가 변경된 것을 인지하기 못합니다. 아래에 소개된 다른 방식은 다수의 위젯이 동일한 정보를 레퍼런스하기를 원하는 경우 유용합니다. 또한 뷰모델을 생성한 다음 설정하는 옵션도 있습니다.
C++에서 콜백을 초기화한 다음이나 블루프린트에서 콜백을 초기화하는 동안 뷰모델을 할당할 수 있습니다. 뷰모델이 설정되어 있지 않은 경우 시스템은 새 인스턴스만 생성합니다. 뷰모델은 PreConstruct 이벤트와 Construct 이벤트 사이에서 생성됩니다.
수동
수동 생성 방식을 사용하면 애플리케이션 코드의 특정 위치에서 뷰모델의 인스턴스를 생성한 다음 이를 위젯에 직접 할당해야 합니다. 위젯은 뷰 모델 오브젝트 레퍼런스를 가지지만 뷰 모델을 할당할 때까지는 Null 값을 가지게 됩니다. 또한 Create Widget 노드에서 생성 시 뷰모델을 할당할 수도 있습니다.
뷰 모델을 할당하면 위젯에 대한 레퍼런스를 구하지 않고 UI를 업데이트하려고 할 때마다 업데이트할 수 있습니다. 이렇게 하면 UI에서 액터 클래스 하나로부터 서로 다른 다수의 위젯에 동일한 뷰모델을 할당할 수 있게 됩니다.
프로퍼티 경로
프로퍼티 경로 생성 방식은 잠재적으로 더 명확한 대안을 제공하며 코드로 지원해야 하는 부분이 적습니다. 다른 클래스가 뷰 모델 레퍼런스를 설정하기 위해 위젯 내에 접근하는 대신 위젯이 일련의 함수 호출에 접근 및 레퍼런스하여 뷰 모델을 가져옵니다. 에디터의 프로퍼티 경로(Property Path) 필드에는 마침표로 구분된 일련의 멤버 이름을 입력할 수 있으며, 이러한 함수 호출의 시작점을 Self라고 가정합니다. 즉, 항상 편집하고 있는 위젯에서 시작합니다.
프로퍼티 경로에서 Self를 직접 지정하면 안됩니다. 프로퍼티 경로 필드는 Self에 대한 레퍼런스로 시작할 것이라고 이미 예상하기 때문입니다.
예를 들어 다음 필드는 위젯의 자체 플레이어 컨트롤러를 구한 다음 현재 제어하고 있는 비히클에 어태치된 뷰모델을 구합니다.
GetPlayerController.Vehicle.ViewModel블루프린트에서 정의한 함수를 호출할 수도 있는데, 이렇게 하면 프로퍼티 경로를 위한 로직을 간소화할 수 있기 때문에 더 높은 유연성을 확보할 수 있습니다. 예를 들어 다음 함수는 위젯을 소유하는 캐릭터에서 캐릭터 체력 뷰 모델을 구합니다.
그런 다음 이 함수의 이름을 프로퍼티 경로로 사용할 수 있습니다.
GetHealthViewModel글로벌 뷰 모델 컬렉션
글로벌 뷰모델 컬렉션은 MVVM 게임 서브시스템(MVVM Game Subsystem)에서 글로벌로 액세스할 수 있는 뷰모델의 목록입니다. 이는 게임의 옵션 메뉴를 위한 세팅과 같이 UI를 통해 액세스해야 하는 변수를 처리하는 데 이상적입니다. 블루프린트에서 글로벌 뷰 모델 컬렉션에 뷰 모델을 추가하려면 다음 단계를 따르세요.
MVVM 게임 서브시스템에 레퍼런스를 추가합니다.
MVVM Game Subsystem 노드에서 핀을 드래그한 다음 Get View Model Collection을 호출합니다.
Get Global View Model Collection 노드에서 핀을 드래그한 다음 Add View Model Instance를 호출합니다.
뷰 모델의 인스턴스를 생성하고 이 노드를 사용하여 컬렉션에 추가할 수 있습니다. 게임 인스턴스 클래스를 사용하면 이를 간편하게 초기화할 수 있습니다.
글로벌 뷰모델 컬렉션을 초기화 모드로 선택하는 경우에는 글로벌 뷰모델 식별자의 Add View Model Instance 노드에서 컨텍스트 이름을 제공해야 합니다. 이 이름은 뷰 모델을 위한 클래스와 일치해야 합니다. 예를 들어 뷰 모델에서 'VM_GraphicsOptions'가 호출된 경우 컨텍스트 이름과 글로벌 뷰 모델 식별자를 모두 제공해야 합니다.
뷰모델의 멤버에 액세스하기
위젯에 뷰 모델을 할당한 후에는 블루프린트에서 위젯의 프로퍼티로 액세스할 수 있습니다. 이는 변수(Variables) > 뷰모델 카테고리에서 찾을 수 있습니다. 뷰 모델에 대한 레퍼런스를 가지고 있으면 뷰 모델의 변수와 함수에 액세스할 수 있습니다.
뷰 모델에 설정된 옵션이 무엇인지에 따라 내부의 모든 함수 또는 Setter에 액세스하지 못할 수도 있습니다.
배열로 작업하기
일반적으로 배열은 뷰 모델에서 액세스할 수 없습니다. 뷰모델에서 배열에 액세스하려면 뷰모델 자체에서 배열을 직접 추가하고 삭제하고 구할 수 있게 FieldNotify 함수를 생성해야 합니다.
뷰(ListView, TreeView, TileView)와 함께 배열을 사용할 수 있습니다. 엘리먼트가 배열 내에서 추가, 제거 또는 이동될 경우 노티파이해야 합니다.
뷰 바인딩
뷰 모델을 생성한 후에는 UMG 에디터에서 뷰 모델을 위젯에 추가하고 '뷰 바인딩' 창으로 타기팅할 수 있습니다.
위젯에 뷰 바인딩 추가하기
위젯에 뷰 바인딩을 추가하는 경우 두 가지 방법을 사용할 수 있습니다. 즉, '디테일(Details)' 패널에서 프로퍼티 바인딩 드롭다운으로 추가하거나 '뷰 바인딩' 메뉴를 사용하여 위젯의 모든 바인딩을 관리할 수 있습니다.
드래그 앤 드롭 사용하기
뷰모델 창에서 위젯에 바인딩할 변수 또는 함수를 클릭하고 바인딩할 영역의 바인드(Bind) 드롭다운으로 드래그합니다. 이것은 뷰 바인딩을 생성하는 가장 간단하고 빠른 방법입니다.
디테일 패널 사용하기
디테일 패널에서 뷰 바인딩을 사용하려면 바인딩을 추가하려는 위젯을 선택한 다음 바인딩하려는 프로퍼티에서 바인드(Bind) 드롭다운을 클릭합니다. 해당 프로퍼티에 유효한 뷰 모델 변수 및 함수는 드롭다운 하단에 표시됩니다. 바인딩을 할당하려면 드롭다운 중 하나를 클릭합니다.
레거시 바인딩 시스템을 비활성화하면 혼란을 방지할 수 있습니다. 이렇게 하려면 프로젝트 세팅(Project Settings) > 에디터(Editor) > 위젯 디자이너(팀)(Widget Designer (Team))으로 이동하여 Property Binding Rule을 Prevent로 설정하세요. 그러면 기존 프로퍼티를 위젯의 파라미터에 바인딩하는 옵션이 제거됩니다.
또한 플러그인 > 모델 뷰 뷰모델(Model View Viewmodel) 섹션에서 디테일 뷰에서 바인딩 허용(Allow Binding from Detail View)을 비활성화하여 뷰모델에 대한 디테일 패널 바인딩도 비활성화할 수 있습니다. 그래도 여전히 '뷰 바인딩' 메뉴를 사용하여 뷰모델 변수를 바인딩할 수 있습니다.
뷰 바인딩 메뉴 사용하기
'뷰 바인딩' 창을 사용하면 뷰 바인딩의 행동 방식을 보다 세부적으로 제어할 수 있습니다. UMG 디자이너 탭에서 창 > 뷰 바인딩(View Binding)을 클릭하여 뷰 바인딩 창을 엽니다.
+ 위젯 추가(Add Widget)를 클릭하여 뷰 바인딩 목록에 추가합니다.
'뷰 모델' 창에서 추가한 모든 뷰 모델을 바인딩할 수 있습니다.
현재 버전의 언리얼 엔진에서는 '뷰 바인딩' 메뉴에서 뷰모델을 바인딩한 다음 디테일 패널을 사용하여 다시 할당할 경우 바인딩이 유효하지 않게 될 수 있습니다. 이를 해결하기 위해서는 '뷰 바인딩' 메뉴에서 바인딩을 삭제한 다음 다시 할당해야 합니다.
뷰 바인딩 환경설정하기
뷰 바인딩에는 다음과 같은 정보가 포함되어 있습니다.
바인딩을 위한 타깃 위젯 및 타깃 뷰모델입니다.
바인딩하려는 위젯 프로퍼티 및 뷰모델 프로퍼티입니다.
두 타깃 프로퍼티 간 정보의 흐름을 결정하는 바인딩의 방향입니다.
바인딩의 업데이트 타입입니다.
바인딩을 비활성화 시 런타임에서 제거하는 활성화/비활성화 토글입니다. 즉, 이 바인딩은 컴파일되지 않으며 런타임에서 사용할 수 없습니다.
다음 섹션에서는 이러한 필드에 대한 세부 내용과 환경설정 방법을 살펴봅니다.
타깃 위젯 선택하기
뷰 바인딩 항목의 첫 번째 드롭다운에서는 뷰 바인딩을 추가할 위젯을 선택합니다. 클릭하면 드롭다운에 위젯의 계층구조가 표시되고 부모 위젯 또는 자손 위젯을 선택할 수 있습니다. 선택을 클릭하여 선택 사항을 확인합니다.
뷰 바인딩 항목 생성하기
타깃 위젯 아래에는 뷰 모델 바인딩을 구성하려는 개별 프로퍼티의 항목이 있습니다. 각 바인딩은 속해 있는 위젯에서 들여쓰기로 표시됩니다. 위젯의 드롭다운 옆에 있는 + 버튼을 클릭하여 단일 위젯에 여러 개의 바인딩을 추가할 수 있습니다. 각 바인딩은 서로 다른 프로퍼티를 타기팅해야 합니다.
위젯 프로퍼티 선택하기
뷰 바인딩 항목의 첫 번째 드롭다운에는 타깃 위젯의 변수 및 함수의 목록이 표시됩니다. 예를 들어 진행률 표시줄 위젯 선택을 사용할 경우 퍼센트 프로퍼티를 사용할 수 있습니다.
이 목록에 표시하기 위해 C++로 정의된 프로퍼티 또는 함수의 경우 UFUNCTION 또는 UPROPERTY 매크로를 사용하여 언리얼 엔진 리플렉션 시스템에 표시할 수 있습니다. 블루프린트에서 정의한 변수 및 함수는 자동으로 사용할 수 있습니다.
뷰 모델 프로퍼티 선택하기
세 번째 드롭다운에서는 타기팅할 뷰 모델과 뷰 바인딩에 사용할 프로퍼티를 선택할 수 있습니다. 클릭하면 이 위젯에 추가한 뷰 모델의 목록이 표시됩니다.
사용하려는 뷰 모델을 클릭하면 뷰 바인딩에 사용할 수 있는 변수 및 함수의 목록이 표시됩니다. 이것은 위젯에 한 방향(One Way To Widget)이기 때문에 변수 및 함수를 여기에 표시하려면 FieldNotify 지정자가 있어야 합니다.
바인딩 방향 설정하기
두 번째 드롭다운에서는 뷰 바인딩의 바인딩 방향을 선택할 수 있습니다. 바인딩 방향은 위젯과 뷰 모델 간 정보가 흐르는 방식을 결정합니다.
사용 가능한 바인딩 방향은 다음과 같습니다.
| 바인딩 방향 | Description |
|---|---|
위젯에 한 번(One Time to Widget) | 바인딩이 뷰모델에서 위젯에 한 번만 적용됩니다. 이로 인해 선택된 위젯 프로퍼티가 업데이트됩니다. |
위젯으로 단방향(One Way to Widget) | 바인딩은 뷰 모델에서 위젯으로만 적용됩니다. 뷰 모델에서 관련 변수를 업데이트할 때마다 위젯에 변수가 변경되었음을 알리고 선택된 위젯 프로퍼티를 업데이트합니다. 또는 함수를 선택한 경우 해당 함수를 호출하면 선택된 위젯 프로퍼티가 업데이트됩니다. |
뷰 모델로 단방향(One Way to Viewmodel) | 바인딩은 위젯에서 뷰 모델로만 적용됩니다. 위젯에서 사용자 또는 코드가 선택된 프로퍼티를 변경할 때마다 해당 변경사항을 뷰 모델 프로퍼티에 적용합니다. 일반적인 예시로는 사용자가 편집한 텍스트 필드 또는 그래픽 옵션이 있습니다. |
양방향 | 바인딩이 두 방향 모두에 적용됩니다. |
모든 뷰모델은 PreConstruct 이벤트와 Construct 이벤트 사이에서 한 번 실행됩니다. 바인딩 방향이 TwoWay인 경우 OneWay 바인딩만 실행됩니다. 뷰모델 값이 SetViewmodel을 사용하여 변경되면 해당 뷰모델을 포함하는 모든 바인딩이 실행됩니다.
변환 함수 사용하기
비히클에 대한 직접 바인딩의 대안으로 변환 함수를 선택할 수 있습니다. 변환 함수는 인티저를 텍스트로 변경하는 것과 같이 뷰 모델의 변수를 다른 타입의 데이터로 변환하기 위한 인터페이스를 제공합습니다. 변환 함수는 뷰 모델 목록 아래의 뷰 모델 프로퍼티 드롭다운에 표시됩니다.
변환 함수를 선택하면 함수의 실행인자를 환경설정할 수 있는 옵션의 목록이 뷰 바인딩의 드롭다운 아래에 표시됩니다.
이러한 프로퍼티 중 하나의 링크 버튼을 클릭하면 뷰모델 값에 해당 프로퍼티를 바인딩할 수 있습니다.
새로운 변환 함수는 글로벌 또는 UserWidget(위젯 블루프린트)에 추가될 수 있습니다. 이 함수는 이벤트, 네트워크, 지원 중단됨 또는 에디터 전용이어서는 안됩니다. 이 함수는 블루프린트에 표시되어야 하고, 하나의 입력 실행인자와 하나의 반환 값을 가져야 합니다. 글로벌로 정의되는 경우, 이 함수는 static이어야 합니다. UserWidget에서 정의되는 경우, 이 함수는 pure 및 const여야 합니다.
뷰 모델 생성 모범 사례
뷰 모델을 생성할 때는 큰 모놀리식 뷰 모델 대신 작고 간결한 뷰 모델을 사용해야 합니다. 이렇게 하면 UI를 디버깅하기가 수월해집니다.
예를 들어 특징, 인벤토리, 히트 포인트로 구성된 완전한 배열을 사용하여 RPG에서 캐릭터를 나타내는 뷰 모델을 생성할 수 있습니다. 하지만 이 뷰모델에 기반하는 UI의 일부를 디버깅하기 위해서는 먼저 전체 캐릭터를 스폰하여 뷰모델의 데이터를 채워야 합니다. 이를 서로 다른 컴포넌트로 분할하면 디버깅할 때 테스트 데이터로 더 쉽게 채워넣을 수 있습니다.
중첩된 뷰 모델
뷰모델을 다른 뷰모델 내부에 중첩하면 복잡한 데이터 세트로 작업할 때 유연성을 높일 수 있습니다.
예를 들어 캐릭터의 체력을 위한 뷰모델과 어트리뷰트(힘, 민첩성, 매직)를 위한 뷰모델을 생성한 다음 전체 캐릭터를 나타내는 뷰모델에 모두 중첩할 수 있습니다. 테스트를 위해 개별 위젯은 연관성 있는 뷰모델에서 데이터를 취할 수 있으며(예를 들어 체력 표시줄은 캐릭터의 체력을 레퍼런스할 수 있음), 최종 결과물에서는 중첩된 뷰모델에서 전체 세트를 사용할 수 있습니다.