UMG Viewmodel

Use Viewmodels to handle events and maintain a manifest for the variables in your UI.

Choose your operating system:

Windows

macOS

Linux

Typically, UI developers break backend data and visual design into separate systems. This makes the process of building the user interface (UI) less destructive and more efficient, as designers can change the visual presentation without breaking the code behind the UI, and programmers can focus on data and systems without needing a completed frontend. The Viewmodel plugin provides a medium for this workflow by introducing Viewmodel assets and View Bindings.

Workflow

Viewmodels contain variables that you can use in your UI. Designers can bind fields in their UI to these using the View Binding panel, while programmers can build the Viewmodels themselves and tie them in with the application's code as they see fit.

Once you add a Viewmodel to a UMG widget, you can access it and call functions or update variables. The Viewmodel pushes updates to any widgets whose fields are bound to its variables.

This is a more efficient alternative to raw attribute binding, as it only updates widgets when you update the variables. It also provides the benefits of an event-driven UI framework without the implementation time setting one up manually.

Required Setup

To use Viewmodels in your project's UI, enable the UMG Viewmodel plugin in the Plugins **menu.

Enabling the Viewmodel plugin in the plugins menu

If you do not enable this plugin, you will not be able to use the UMVVMViewModelBase class, and you will not be able to use View Bindings in UMG.

Viewmodels

Viewmodels have two main purposes:

  • Maintain a manifest of the variables needed for your UI.

  • Provide a medium of communication between your UI and the rest of your application.

When you need your UI to be aware of a variable, you can add it to a Viewmodel, then add the Viewmodel to your widget and bind fields to it. When you need to update your variables, you can get a reference to the Viewmodel and set them from there. They then notify the widgets bound to those variables about the changes and update them.

Create a Viewmodel

You can create a Viewmodel in C++ by extending the UMVVMViewModelBase class, or by extending another Viewmodel class. Viewmodels are UObjects that depend on FieldNotify variables and functions to broadcast changes to widgets that are bound to them.

It will be possible to create Viewmodels with Blueprint in a future release of Unreal Engine.

Variables with FieldNotifies

When you define variables in your Viewmodel, each variable should be Private, and must have a UPROPERTY macro with the FieldNotify specifier. The full list of specifiers used for FieldNotify variables is as follows:

UPROPERTY Specifier

Description

FieldNotify

Broadcasts a notification to any widgets bound to this variable.

Setter

States that the variable should allow setting its value. This assumes that the Setter function will have a name with the format Set[Variable Name]

Setter="[FUNCTION_NAME]"

As Setter, but you can provide the name of a custom function to use it as the Setter.

Getter

States that the variable should allow retrieving its value. This assumes that the Getter function will have a name with the format Get[VariableName]

Getter="[FUNCTION_NAME]"

As Getter, but you can provide the name of a custom function to use it as the Getter.

The FieldNotify specifier is required to broadcast value changes to widgets. Any variable with this specifier will appear in the View Binding menu.

You can decide whether to provide the Setter or Getter specifiers. If you decide not to provide one of them, you will not be able to perform that operation outside of this class. Specifying only the Getter and Setter specifiers without a function name is sufficient when you only want to trigger a notification for the variable itself.

Custom Getters and Setters are useful when:

  • You need to perform an operation before retrieving a variable.

  • You want to trigger other functions or update other variables when setting a variable.

For example, if you want to create a health bar using a Progress Bar widget, you would need to retrieve a percent value representing how much of the character's maximum health is left, as the Progress Bar uses a percentile value to determine how much it should be filled. In this case, you would define a custom Setter for the character's current health, then have it trigger a separate notify for returning the percentage of the character's maximum health.

UFUNCTION(BlueprintCallable)
void SetCurrentHealth(int newCurrentHealth)
{
    if (CurrentHealth != newCurrentHealth)
    {
        UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED(CurrentHealth, newCurrentHealth);
        UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED(GetHealthPercent);
    }
}

If you create custom Getter or Setter functions, do not make them UFUNCTIONS, as it will create redundant listings for Get and Set functions in Blueprint. The UPROPERTY macro for the variable already provides access to these in the form of the variable's Get and Set nodes. You should also make any custom Getters const functions, as their only job should be returning a value.

Functions with FieldNotifies

You can create custom functions that broadcast FieldNotifies, and you can bind widgets' properties to these functions the same way as you can with variables. Functions used in this way must follow these requirements:

  • They must have the UFUNCTION macro with the FieldNotify and BlueprintPure specifiers.

  • They must take no arguments.

  • They must be const functions.

  • They must return only a single value.

For example, the following function is a FieldNotify for returning the percent value of a character's current health divided by their maximum health:

UFUNCTION(BlueprintPure, FieldNotify)
float GetHealthPercent() const
{
    //Check to avoid dividing by zero
    if (MaxHealth != 0)
    {
        return (float) CurrentHealth / (float) MaxHealth;
    }
    else
    {
        return 0;
    }
}

Triggering FieldNotifies with Macros

When changing variables, functions need to call one of the Viewmodel notification macros to broadcast changes to bound widgets. The list of available macros is as follows:

ViewModel Macro

Description

UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED([Member name])

Broadcasts an event after the field value is changed.

UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED_WITH_REP([Member name])

Replicates the field value over a network game, then broadcasts an event after the field value is changed.

UE_MVVM_SET_PROPERTY_VALUE([Member Name], [New Value])

Test if the value of the field has changed, then set the new value of the field and send a notification to bound widgets.

UE_MVVM_SET_PROPERTY_VALUE_WITH_REP)[Member Name], [New Value])

As UE_MVVM_SET_PROPERTY_VALUE, and then replicate it and send a notification to bound widgets.

The SET_PROPERTY_VALUE macros do the same thing as BROADCAST_FIELD_VALUE macros, except that the SET_PROPERTY_VALUE macros check to see if the value changed before broadcasting. This is a very common check when creating Setters for Viewmodels, and it is included for convenience.

The BROADCAST_FIELD_VALUE_CHANGED macros can take either the variable itself, if you want to notify widgets bound directly to that value, or they can take the names of functions. This can be useful if you want a widget bound to values that are derived or converted from other variables, but do not want to create an extra variable to hold that information.

Example

The following code snippet is an example of a Viewmodel class using the above concepts. GetHealthPercent is defined as a separate function from the Getters and Setters, but the Setters call it in addition to notifying when the variables themselves are changed.

UCLASS(BlueprintType)
class UVMCharacterHealth : public UMVVMViewModelBase
{
GENERATED_BODY()
public:
    UPROPERTY(BlueprintReadWrite, FieldNotify, Setter, Getter)
    int32 CurrentHealth;

    UPROPERTY(BlueprintReadWrite, FieldNotify, Setter, Getter)
    int32 MaxHealth;

private:
    void SetCurrentHealth(int32 newCurrentHealth)
    {
        if (CurrentHealth != newCurrentHealth)
        {
            UE_MVVM_SET_PROPERTY_VALUE(CurrentHealth, newCurrentHealth);
            UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED(GetHealthPercent);
        }
    }

    void SetMaxHealth(int32 newMaxHealth)
    {
        if (MaxHealth != newMaxHealth)
        {
            UE_MVVM_SET_PROPERTY_VALUE(MaxHealth, newMaxHealth);
            UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED(GetHealthPercent);
        }
    }

    int32 GetCurrentHealth() const
    {
        return CurrentHealth;
    }

    int32 GetMaxHealth() const
    {
        return MaxHealth;
    }

public:
    UFUNCTION(BlueprintPure, FieldNotify)
    float GetHealthPercent() const
    {
        if (MaxHealth != 0)
        {
            return (float) CurrentHealth / (float) MaxHealth;
        }

        else
            return 0;
    }
};

Add a Viewmodel to a Widget

You can add Viewmodels to a widget in the Viewmodels window in UMG. You can find this under Window > Viewmodels in the UMG Designer tab.

Locating the Viewmodel window in the Window dropdown

Click the + Viewmodel button to select one of your project's Viewmodels, then click Select.

Initialize Your Viewmodel

When you click a Viewmodel in the Viewmodels window, you can choose how to initialize it with the Creation Type setting. The following methods are available:

Viewmodel Creation Type

Description

Create Instance

The widget automatically creates its own instance of the Viewmodel.

Manual

The widget initializes with the Viewmodel as null, and you need to manually create an instance and assign it.

Global Viewmodel Collection

Refers to a globally-available Viewmodel that can be used by any widget in your project. Requires a Global Viewmodel Identifier.

Property Path

At initialization, execute a function to find the Viewmodel. The Viewmodel Property Path uses member names separated by periods. For example: GetPlayerController().Vehicle.Wheel[0].ViewModel. Property paths are always relative to the widget.

Viewmodels do not necessarily have a one-to-one relationship with widgets. There are multiple ways to set them up and assign them to widgets, and it is possible for multiple widgets to take information from a single Viewmodel. Each creation type method is detailed below.

Create Instance

The Create Instance creation method automatically creates a new instance of the Viewmodel for each unique instance of the widget. This means, if you have several copies of the same widget in the viewport, and you change the Viewmodel variables for one of them, only that widget will update, while all the other copies will remain the same. Similarly, if you create multiple different widgets that use the same Viewmodel, none of those widgets will be aware of changes to each other's information. The other methods below are useful for when you want multiple widgets to reference the same data.

Manual

The Manual creation method requires you to create an instance of the Viewmodel yourself somewhere in your application's code, then assign it to the widget manually. The widget has a Viewmodel object reference, but it will have a null value until you assign a Viewmodel to it. Once you have assigned your Viewmodel, you can update it whenever you want to update your UI without getting any references to widgets.

This provides an opportunity to assign the same Viewmodel to multiple different widgets in your UI.

Property Paths

The Property Path creation method provides an alternative that is potentially cleaner and requires less code support. Instead of other classes reaching inside the widget to set its Viewmodel reference, the widget reaches out with a series of function calls and references to fetch the Viewmodel. The Property Path field in the editor expects a series of member names separated by periods, and it assumes that the starting point for calling these functions is Self. In other words, it always starts at the widget you are editing.

Do not manually specify Self in your Property Paths, as the Property Path field already assumes you are starting with a reference to Self.

As an example, the following field gets the owning player controller of the widget, then gets a Viewmodel attached to the first wheel on the vehicle it is currently controlling:

GetPlayerController().Vehicle.Wheel[0].ViewModel

You can also call functions you define in your Blueprint, which can help condense the logic for your Property Paths and provide extra flexibility. For example, the following function gets the Character Health Viewmodel from the character who owns the widget:

You can then use this function's name as the Property Path:

GetHealthViewModel()

Global Viewmodel Collection

The Global Viewmodel Collection is a globally accessible list of Viewmodels in the MVVM Subsystem. These are ideal for handling variables that may need to be accessed throughout your UI, such as settings for your game's option's menu. To add a Viewmodel to the Global Viewmodel Collection in Blueprint, follow these steps:

  1. Add a reference to the MVVM Subsystem.

  2. Drag a pin from the MVVM Subsystem node, then call Get Global Viewmodel Collection.

  3. Drag a pin from the Global Viewmodel collection, then call Add Viewmodel Instance.

You can then construct an instance of the Viewmodel and add it to the collection with this node. The Game Instance class is a convenient place to initialize these.

When choosing Global Viewmodel Collection as an initialization mode, provide the Context Name from your Add Viewmodel Instance node in the Global Viewmodel Identifier. This name must match the class name for the Viewmodel. For example, if your Viewmodel is called VM_GraphicsOptions you would provide that as both the Context Name and the Global Viewmodel Identifier.

Access Your Viewmodel's Members

After you have assigned a Viewmodel to a widget, you can access it as a property of the widget in your Blueprint. It will be located under the Variables > Viewmodel category. Once you have a reference to a Viewmodel, you can access its variables and functions.

Depending on what options are configured in the Viewmodel, you may not have access to all internal functions or Setters.

Working With Arrays

Arrays are not normally accessible in Viewmodels. To access an array in your Viewmodel, create your own FieldNotify functions to add, remove, and get members in the array directly from the Viewmodel itself.

Best Practices for Creating Viewmodels

When creating your Viewmodels, you should use small, concise Viewmodels instead of large, monolithic ones. This practice makes debugging your UI easier.

For example, you could create a Viewmodel representing a Character in an RPG, with a complete array of characteristics, an inventory, and hit points. However, to debug any part of the UI that depends on this Viewmodel, you would first need to spawn an entire character to fill the Viewmodel's data. If you split these up into different components, you can more easily fill them with test data when debugging.

You can nest Viewmodels inside other Viewmodels. This can be useful for representing complex sets of data.

View Bindings

After you have created a Viewmodel, you can add it to a widget in the UMG editor and target it with the View Bindings window.

Add a View Binding to a Widget

There are two methods for adding View Bindings to widgets: you can add them with the property binding dropdown in the Details panel, or you can use the View Binding menu to manage all of your widget's bindings.

Using the Details Panel

To use View Bindings in the Details Panel, select the widget you want to add a binding to, then click the Bind dropdown on the property you want to bind. Any Viewmodel variables and functions that are valid for that property will appear at the bottom of the dropdown. Click one to assign the binding.

Binding a Viewmodel to a property in the Details panel

Using the View Binding Menu

The View Binding window offers more detailed control over how your View Bindings behave. Open the View Binding window by clicking Window > View Binding in the UMG Designer tab.

Locating the View Binding menu in the Window dropdown

Click + Add Widget to add an entry to the View Binding list.

Adding a widget to the View Binding list

Any Viewmodel you have added in the Viewmodels window is eligible for bindings.

In the current version of Unreal Engine, if you bind a Viewmodel with the View Bindings menu, then reassign it with the Details panel, the binding might become invalid. To fix this, you should delete the binding from the View Bindings menu, then reassign it.

Configure Your View Binding

View Bindings contain the following information:

  • The target widget and target Viewmodel** for the binding.

  • The widget property and Viewmodel property that you want to bind to one another.

  • The direction of the binding, which determines the flow of information between the two target properties.

  • The update type of the binding.

  • The enabled / disabled toggle, which turns the binding on and off.

The following sections provide details about each of these fields and how to configure them.

Choose the Target Widget

The first dropdown for a View Binding entry chooses the widget you want to add the View Binding to. When you click it, the dropdown shows the hierarchy for your widget, and you can choose either the parent widget itself or any of its child widgets. Click Select to confirm your selection.

Selecting the widget you want to target for a View Binding

Create View Binding Entries

Underneath the target widget, there are entries for individual properties you want to set up Viewmodel bindings for. Each binding is indented from the widget that it belongs to. You can add multiple bindings for a single widget by clicking the + button next to the widget's dropdown. Each binding must target a different property.

Adding View Binding entries to a target widget

Select the Widget Property

The first dropdown in a View Binding entry displays a list of the target widget's variables and functions. For example, if you use a select Progress Bar widget, the Percent property will be available.

For a property or function defined in C++ to appear in this list, it must be visible to the Unreal Engine reflection system with the UFUNCTION or UPROPERTY macros. Blueprint-defined variables and functions are automatically available.

Select the Viewmodel Property

The third dropdown selects both the Viewmodel you want to target, as well as which of its properties you want to use for the View Binding. When you click it, it displays a list of the Viewmodels you added to this widget.

Choosing the target property for a View Binding

Click the Viewmodel you want to use to display a list of variables and functions that are viable for View Bindings. For variables and functions to appear here, they must have the FieldNotify specifier.

Set The Bind Direction

The second dropdown selects the Bind Direction for the View Binding. This determines how information flows between the widget and the Viewmodel.

The bind direction dropdown

The available bind directions are as follows:

Bind Direction

Description

One Way to Widget

The binding applies only from the Viewmodel to the widget. Any time you update the corresponding variable in the Viewmodel, it notifies the widget that the variable has changed and updates the selected widget property. Alternatively, if you chose a function, calling that function updates the selected widget property.

One Way to Viewmodel

The binding applies only from the widget to the Viewmodel. Any time either the user or your code changes the selected property in the widget, it applies that change to the Viewmodel property. Typical examples include user-edited text fields or graphics options.

Two Way

The binding applies in both directions.

Using Conversion Functions

As an alternative to binding directly to a variable, you can select Conversion Functions. These provide an interface for translating variables from your Viewmodel into different types of data, such as changing integers into text. Conversion Functions appear in the Viewmodel property dropdown underneath the list of Viewmodels.

When you choose a Conversion Function, a list of options for configuring that function's arguments appears beneath the dropdowns for the View Binding.

A list of the options for conversion functions in the View Bindings menu

If you click the link button for one of these properties, you can bind that property to any Viewmodel value.

Adding a value to a conversion function