はじめに
Unreal Engine (UE) Advent Calendar 2025 の7日目の記事です!
この記事では Unreal Engine の「UMG Viewmodel」という機能について解説します。
この記事での環境は以下の通りです。
- Windows 11
- UE 5.7.0(ランチャー版)
- UMG Viewmodel 1.0(Beta)
UMG Viewmodel とは
「UMG Viewmodel」とは何でしょうか?
UMG Viewmodel とは UMG ウィジェット(View)とゲームのデータやロジック(Model)を分離させて、View と Model の双方向のやり取りを疎結合な状態で効率的に行えるようにするための機能です。
MVVM(Model-View-ViewModel)とは
UMG Viewmodel を使用すると UMG ウィジェットと、それとやり取りするロジック部分の実装において MVVM(Model-View-ViewModel)というものを簡単に実現できるのですが、この MVVM とは何でしょうか?
MVVM とは「Model-View-ViewModel」の略であり、その名の通り Model、View、ViewModel という3つの要素から成り立っています。
(「ViewModel」は「VM」と略されることがあります。)
各要素の役割は以下の通りです。
| 要素 | 役割 |
|---|---|
| Model | データを取得してそのデータを読み取ったり、書き込んだりする。 (ビジネスロジックを担当する。) この記事では ViewModel で定義した変数を扱っている。 |
| View | ユーザーに情報を表示したり、ユーザーからの入力を受け取ったりする。 この記事ではウィジェットブループリントが View。 |
| ViewModel | Model と View の仲介役。 データバインディングという仕組みを使って Model と View の値を同期させる。 この記事では MVVMViewModelBase というクラスを継承したクラスが ViewModel。 |
これら3つの要素を図で表すとこの画像のようになります。
この画像では「UMG Widget」が View で、「Object in Application」が Model になっています。

UI 部分の実装において MVVM を利用するメリットはいくつかありますが、UMG Viewmodel を使用すると MVVM の役割ごとに完全に別のアセットになるので、プログラマーとデザイナーが同時に作業しやすくなったり、データを扱って何か処理を行うロジックの部分をあまり意識することなく比較的自由に UI を編集できるようになったりといった点が最も大きなメリットかと思います。
後に解説する手順通りに進めると Model、View、ViewModel の Reference Viewer はそれぞれ以下のようになります。



これらの画像はつまり、「Model と View は ViewModel のことは知っているけど、お互いのことは全く知らず、ViewModel は誰のことも知らない」という状態です。
なので ViewModel さえ存在していて、必要な変数や関数などが ViewModel で定義されていれば仮に Model と View の片方しか存在していない状態でもエラーが発生することなく開発を進めることができます。

公式チュートリアルをやってみる
ここからはとりあえず公式ドキュメントのチュートリアルを進めてみます。
(後半はオリジナルの手順ですが)
プラグインの有効化
まずは「UMG Viewmodel」というプラグインを有効化します。
「Edit > Plugins > ALL PLUGINS」で全てのプラグインが表示されている状態で「viewmodel」などと検索して「UMG Viewmodel」にチェックを付けます。

UMG Viewmodel はこの記事の執筆時点ではまだベータ機能なのでこの画像のような警告が表示されるかと思いますが、「Yes」を押します。

この画像のようなメッセージが下に表示されるので「Restart Now」を押してエディタを再起動します。

ViewModel の作成
次は ViewModel となるブループリントを作成して Field Notify 変数と Field Notify 関数を追加します。
コンテンツブラウザで右クリックして「Blueprint Class」を選択します。
親クラスを選択するウィンドウが開くので「ALL CLASSES」で「viewmodel」などと検索して「MVVMViewModelBase (MVVM Base Viewmodel)」を選択し、「Select」を押します。

ここではわかりやすいように「BP_ViewModel」という名前にしました。

作成したブループリントをダブルクリックして開き、「CurrentHealth」と「MaxHealth」という Float 型の変数を追加して初期値を設定します。
今回はどちらも初期値を10にしました。

これらの変数の右側にあるベルアイコンのボタンを押して Field Notify にします。

以下のような「GetHealthPercent」という関数を追加します。

この関数も Field Notify にする必要があるのですが、上の画像の状態だと My Blueprint でも Details でもそのプロパティがグレーアウトして有効化できない状態になってしまっています。


この場合はその関数を選択している状態で Details から「Pure」と「Const」にチェックを付けるとその関数を Field Notify にできるようになります。

関数を Field Notify にするための条件は以下の4つです。
- ピュア関数であること
- Const であること
- アウトプット(戻り値)が1つのみあること
- インプット(引数)がないこと
変数のときと同様にして GetHealthPercent() も Field Notify にします。

CurrentHealth を選択している状態で「Details > Variables > Field Notify」の右の「v」のボタンを押して「GetHealthPercent」を選択します。

同様の操作を MaxHealth に対しても行います。
これで CurrentHealth や MaxHealth の値が変更された(ブロードキャストされた)時に GetHealthPercent() も自動的にブロードキャストされるようになりました。
View の作成
次は View となるウィジェットブループリントを作成します。
コンテンツブラウザで右クリックして「User Interface > Widget Blueprint」を選択します。
親クラスを選択するウィンドウが開くので「User Widget」を選択します。

ここではわかりやすいように「WBP_View」という名前にしました。

Window から「View Bindings」と「Viewmodels」を選択してこれらのウィンドウを画面に追加します。

「Viewmodels > + Viewmodel」を押して先ほど作成した ViewModel を選択し、「Select」を押します。

下の画像のように Hierarchy に Canvas Panel と Progress Bar を追加します。
今回はわかりやすいように Progress Bar を「ProgressBar_HealthPercent」という名前に変更しました。

「View Bindings > + Add Widget」を押して要素を追加します。
追加した要素の「v」を押して先ほど Hierarchy に追加した Progress Bar を選択し、「Select」を押します。

追加した要素の鉛筆マークのある部分を押してその Progress Bar の「Percent」を選択し、「Select」を押します。

矢印の右側の鉛筆マークのある部分を押して「{作成した ViewModel} > Get Health Percent」を選択し、「Select」を押します。

以下のような状態になっていれば OK です。

Model の作成
次は Model となるブループリントを作成します。
コンテンツブラウザで右クリックして「Blueprint Class」を選択します。
親クラスを選択するウィンドウが開くので今回は「Actor」を押します。

ここではわかりやすいように「BP_Model」という名前にしました。

作成したブループリントをダブルクリックして開き、自作の ViewModel 型の「ViewModel」という変数を追加します。

その変数を選択している状態で Details から Instance Editable と Expose on Spawn にチェックを付けます。
これにより、このアクタをスポーンさせる時に外部から ViewModel を注入できるようになりました。

ViewModel の CurrentHealth の値を変更する処理をそのアクタに追加します。
今回は以下のように、Enter キーが押されるたびに CurrentHealth の値を1減らすという処理を追加しました。

Model、View、ViewModel のインスタンス化
最後に Model、View、ViewModel をインスタンス化する処理を作成します。
今回はレベルブループリントにそれらの処理を追加します。

今回、レベルブループリントに追加した処理の概要は以下の通りです。
- ViewModel をインスタンス化してレベルブループリントの変数に保持する
- Model をインスタンス化して ViewModel をそれに渡す
- View をインスタンス化して ViewModel をそれに渡し、ビューポートに追加する



テスト
この状態でゲームを実行すると Enter キーを押すたびにバーが減っていき、Model が ViewModel の値を操作して、その変更が View に反映されているのがわかるかと思います。

従来のバインディング方法じゃダメなの?
公式チュートリアルを終えた自分は「わざわざウィジェットと ViewModel の変数/関数を View Bindings でバインドしなくても、従来のバインディング方法でバインドしちゃダメなの?」と疑問に思いました。
結論としては従来のバインディング方法では値が変更されたかどうかに関わらず、UI を更新する処理が毎フレーム呼ばれてしまいます。
なので制限時間タイマーなどの値が毎フレーム変わるものに対しては従来のバインディング方法を使用しても良いのかもしれませんが、そうでない場合(値が変更された時だけ UI を更新したい場合)は UMG Viewmodel のバインディングを使用した方が良いかと思います。
検証
ここからは UMG Viewmodel のバインディングを使用したときと、従来のバインディング方法でバインドしたときの違いをサクッと確認してみます。
まずは ViewModel で定義した GetHealthPercent() に PrintString を仕込みます。

UMG Viewmodel のバインディングを使用した場合
UMG Viewmodel のバインディングを使用している、公式チュートリアルの状態でゲームを実行すると CurrentHealth の値が変更された時だけ GetHealthPercent() が呼び出されているのがわかるかと思います。

従来のバインディング方法を使用した場合
では従来のバインディング方法でバインドした場合はどうでしょうか?
ウィジェットブループリントを開いて View Bindings で全てのバインディングを Remove し、Viewmodels も削除して空の状態にします。


Designer から Graph に切り替えて自作の ViewModel 型の変数を追加します。

その変数を選択している状態で Details から Instance Editable と Expose on Spawn にチェックを付けます。
これにより、このウィジェットブループリントをインスタンス化する時に外部から ViewModel を注入できるようになりました。

Designer に戻って Progress Bar を選択し、「Details > Progress > Percent」の右のクリップマークを押し、「+ Create Binding」を選択します。

「Get_{Progress Bar の名前}_Percent」という名前の関数が作成されるので ViewModel の GetHealthPercent() の戻り値を返す処理を組みます。

レベルブループリントにある、ウィジェットブループリントのインスタンス化の部分でエラーが発生している場合は ViewModel のピンを繋ぎ直してあげます。

これで UMG Viewmodel のバインディングを使用したときと同じように「Model と View は ViewModel のことは知っているけど、お互いのことは全く知らず、ViewModel は誰のことも知らない」という状態を維持できました。
この状態でゲームを実行すると CurrentHealth の値が変更されたかどうかに関わらず、GetHealthPercent() が毎フレーム呼び出されてしまっているのがわかるかと思います。

このように、Model が ViewModel の値を変更した時だけ View を更新したい場合は従来のバインディング方法ではなく、UMG Viewmodel のバインディングを使用した方が良いかと思います。
Creation Type
ウィジェットブループリントの Viewmodels で追加した ViewModel を選択している状態で Details から「Creation Type」というものを設定できるので、ここからは各 Creation Type でどのような違いがあるのかをまとめてみます。

Manual
まずは Manual についてです。
デフォルトで設定されている Creation Type はこの Manual かと思います。
Creation Type を Manual に設定するとそのウィジェットブループリントをインスタンス化する際、Viewmodels で追加した ViewModel のピンが出現します。

公式チュートリアルのようにウィジェットブループリントをインスタンス化する時に ViewModel も手動でインスタンス化してウィジェットブループリントに渡すか、そのウィジェットブループリント内などの他の場所や他のタイミングで ViewModel を手動でインスタンス化して View に保持させる必要があります。
なので、例えば以下のように ViewModel のピンに何も接続していない状態でそのウィジェットブループリントをインスタンス化してビューポートに追加後、そのウィジェットブループリントの持っている ViewModel が有効かどうか確認してみます。


この場合は「false」と表示され、ViewModel が無効な状態になっているのがわかります。
ウィジェットブループリントをインスタンス化する時に ViewModel も手動でインスタンス化して、それを渡してあげると「true」と表示されます。
Create Instance
次は Create Instance についてです。
Create Instance については公式ドキュメントで以下のように説明されています。
ウィジェットによってビューモデルの独自のインスタンスが自動的に作成されます。
UMG ビューモデル
Creation Type を Create Instance に設定すると「Create {ウィジェットブループリント名} Widget」に ViewModel のピンが表示されなくなります。

この状態で先ほどと同様に AddToViewport 後に ViewModel の状態を確認してみると「true」と表示されます。
Manual のときとは違って、ViewModel を手動で作成しなくても自動的に作成されたことがわかります。
Global Viewmodel Collection
次は Global Viewmodel Collection についてです。
Global Viewmodel Collection については公式ドキュメントで以下のように説明されています。
「グローバル ビューモデル コレクション」とは、MVVM ゲーム サブシステムにおける、グローバルにアクセス可能なビューモデルのリストです。 これらは、ゲーム オプション メニューの設定など、UI 全体を通じてアクセスする必要がある可能性がある変数の処理に適しています。
UMG ビューモデル
Manual では ViewModel を手動でインスタンス化して管理する必要があり、Create Instance ではウィジェットブループリントのインスタンス化時に自動的に ViewModel もインスタンス化されるものの、その ViewModel を取得するときはそのウィジェットブループリントから取得する必要がありました。
しかし、Creation Type を Global Viewmodel Collection に設定すると、手動でインスタンス化した ViewModel を「Viewmodel Game Subsystem」というサブシステムに登録して他の場所からそれにアクセスできるようになります。
ViewModel を Viewmodel Game Subsystem に登録する処理に関しては公式ドキュメントで以下のように書かれていました。
これらの初期化には Game Instance クラスが便利です。
UMG ビューモデル
なので BP_GameInstance というゲームインスタンスを作成して Init() に以下の処理を追加してみました。
ViewModel(BP_ViewModel)をインスタンス化して、それを Viewmodel Game Subsystem → Get View Model Collection → Add View Model Instance に渡しています。
また、MVVM View Model Context という構造体も作成して Add View Model Instance に渡しています。

これまでは Model(BP_Model)外でインスタンス化した ViewModel を Model に注入していましたが、Global Viewmodel Collection では ViewModel が Viewmodel Game Subsystem に登録されているので、Model 内で ViewModel の値を変更する処理は以下のように書き換えることもできます。

Model と View のインスタンス化を行っているレベルブループリントは以下のようになりました。
ここでは ViewModel をインスタンス化したり、それを Model や View に渡したりといったこともしていません。

Property Path
次は Property Path についてです。
Creation Type を Property Path に変更すると、そのプロパティのすぐ下に「Viewmodel Property Path」というプロパティが出現します。

この Viewmodel Property Path に設定すべき値については公式ドキュメントで以下のように説明されています。
エディタ内の [Property Path] フィールドには、ピリオドで区切られた一連のメンバー名を入力します。
UMG ビューモデル
また、公式ドキュメントでは「GetPlayerController.Vehicle.ViewModel」という文字列が例として挙げられています。
今回は View(WBP_View)で GetViewModel() という、ViewModel を返す関数を追加してみました。
(この画像では Viewmodel Game Subsystem から Find View Model Instance したものを返していますが、ViewModel さえ返していればここの処理は何でもいいです。)

Graph から Designer に戻って Viewmodel Property Path を「GetViewModel」に変更します。

この状態でコンパイルすると「Viewodel ‘BP_ViewModel’: Viewmodel has an invalid Getter. Function ‘Get View Model’ is not readable at runtime.」というコンパイルエラーが発生してしまいましたが、GetViewModel() の「Details > Graph > Advanced > Const」にチェックを付けてその関数を const にするとコンパイルエラーが発生しなくなりました。

このように Creation Type を Property Path に設定すると、その View が ViewModel を取得するときに自作の関数を使用するようにできます。
Resolver
最後は Resolver についてです。
Resolver は UE 5.3 で新たに追加された Creation Type であり、この記事の執筆時点では Resolver についての説明は公式ドキュメントに記載されていません。
Added Resolver, a new way to select a Viewmodel. You can extend the Resolver and can implement your own logic on own to find/create the Viewmodel.
Unreal Engine 5.3 リリース ノート
Creation Type を Resolver に設定すると、View が特定の Resolver を使用して ViewModel を取得するようになります。
実際に試してみます。
まずはコンテンツブラウザで右クリックして「Blueprint Class」を選択します。
親クラスを選択するウィンドウが開くので「ALL CLASSES」で「viewmodel」などと検索して「MVVMViewModelContextResolver (Viewmodel Resolver)」を選択し、「Select」を押します。

ここではわかりやすいように「BP_ViewModelResolver」という名前にしました。

作成したブループリントをダブルクリックして開き、「My Blueprint > FUNCTIONS」の右の「Override」を押して「Create Instance」を選択します。

ViewModel を取得して返す処理を CreateInstance() に追加します。
(この画像では Viewmodel Game Subsystem から Find View Model Instance したものを返していますが、ViewModel さえ返していればここの処理は何でもいいです。)

View のウィジェットブループリントを開いて Viewmodels で ViewModel を選択し、「Details > Viewmodel > Resolver」を自作のものに変更します。

これにより、この View は「BP_ViewModelResolver」という自作の Resolver を使用して ViewModel を取得するようになりました。
最後に
参考記事・動画
基本用語
MVC / MVVM
- いまさら人に聞けないMVVMの概要
- (初級)MVCとMVVMという2つのアーキテクチャパターンの説明
- MVCとMVVMの違い
- 『MVC』 と『MVVM』の違いについて
- ソフトウェアアーキテクチャー…?MVCやMVVMってなに!?
UMG Viewmodel
- UE5 UMG ViewModelを利用してBPオンリーのMVVMをしてみる
- UMG ViewModelについて
- UMG ビューモデル
- Unreal ViewModels で UI コミュニケーションをレベルアップ





















