皆様いかがお過ごしでしょうか。歌乃です。

最近UEを弄り回してます。下手なゲームより面白い。

今回はUIの実装に関してです。

というのもGameplayAbilitySystemの実装でキャラクターにゲーム内で使用する「能力」を与えることができたので、能力の使用によるコスト(消費体力とかスタミナとか魔力とか)を実装した際にゲーム内でユーザーに情報を与えるためのUIが必要になったためです。

以下のような読者を対象にしてます。

  • UEの基本操作がわかり、BluePrintで簡単な処理を作れる。またはBPのサンプルを触ったことがある。

前回の記事 > Gameplay Abilities を使ってみる



Unreal Motion Graphics UI デザイナ(UMG)

UEのゲームプロジェクト(GameModeクラス)には基本のUIとしてHUDというクラスが用意されているのですが、私の理解が浅いせいで、いまいち利便性がわかりません( ゚д゚)

ネットの記事には「UMGの登場によってHUDで実現していたことはだいたいUMGでできるようになった」的な話もみかけるので、HUDクラスは放置して、HUDもUIもUMGで実装してしまえばいいじゃない。という結論に。

さて前述のUMG(Unreal Motion Graphics UI デザイナ)ですがWidgetと呼ばれるコンポーネント(のBP)を使用してグラフィカルなデザイナーエディタ上でUIを構築することの出来る機能です。

UMG(Unreal Motion Graphics)



ステータス表示用のUIウィジェットを作る

新規作成でユーザーインターフェースからウィジェットブループリントを選びます。

ウィジェットブループリント

親クラスとして「UserWidget」を選択します。

UserWidget

新規作成したBPを開くと、左にコンポーネント(widget)の一覧が表示されたパレットと、配置されたwidgetの階層ツリーが表示され、右(または中央)にはウィジェットの外観を確認できるデザイナが表示されます。

デザイナー

パレットから配置したいウィジェットを「デザイナ」上にドラッグするか「階層ツリー」にドラッグして配置します。

配置後に「詳細」パネルで見た目やサイズを調整していきます。

詳細パネル

デザイナーは使わないのか?という声が聞こえそうですが、使いません。というか私はうまく使えませんでした。



UMGのウィジェットは大抵のものが見た目のサイズ指定ができません

様々なデバイスの画面サイズに柔軟に対応させるという設計思想のため、なのだと思われます。

ですが、サイズが決まらないとデザインも捗らないと思います。なので私はデザイナの表示を「Custom」または「Custom on Screen」に設定し、幅と高さを目的のUIサイズに設定してデザインするようにしています。

Custom on Screen

設定した幅と高さは、デザイナの表示領域を設定するもので、ウィジェットの幅と高さを決めるものではないことに注意してください。



今回は「体力」「魔力」「スタミナ」の三つをバーで表示させることにします(体力と魔力は使ってませんが今後を考えて作っておきます)。

UMGのウィジェットには基本的なUIが用意されています。その中には進捗状況を表示させるのに使えるProgressBarが用意されていますが、今回はそれをスタミナゲージとして流用しました。

ウィジェットの階層はこんな感じです。

[WidgetRoot]
┗[Uniform Grid Panel]
 ┣[InvalidationBox]
 ┃┗[Uniform Grid Panel]
 ┃ ┣[ProgressBar]
 ┃ ┗[ScaleBox]
 ┃  ┗[Border]
 ┃   ┗[Text]
 ︙

[InvalidationBox] 以下は同じものの繰り返しで三つ分のバーを作ってます。

軽く説明を入れると、InvalidationBoxは変更がなければキャッシュを利用して以下のUIウィジェットの描画等をスキップすることでパフォーマンスを上げる効果があります。

Uniform Grid Panelはhtmlのtableタグのように行と列を指定してウィジェットを配置できるコンテナです。

ScaleBoxは画面に合わせて子ウィジェットの大きさを調整してくれます。大体どのウィジェットも画面サイズに追従して大きさが変更されるのですが、テキストや画像などは拡縮にくせがあるので、ScaleBoxでラップすることで大きさを枠内に収めてくれます。

Borderはバックグラウンドの見た目やパディングを設定できるコンテナで項目間の見た目調整に便利です。

ProgressBarとTextは説明の必要はないでしょう。



イベントの処理を作る

デザイナで見た目部分ができたら、イベントグラフで動作部分を作っていきます。

イベントグラフ

デフォルトでは EventConstruct から処理を繋いで行きますが、EventConstruct は複数回呼ばれることがあるので、最初の一回だけ呼ばれるEvent On Initialized から処理を繋いでいます。

それというのもウィジェット側でイベントを管理するのではなく、プレイヤーキャラクタ側でイベントを管理して、更新処理のみをウィジェット側でおこなうように実装したためです。

ちなみに更新処理イベントの内容はこんな感じです。

更新処理イベント

プログレスバーは0.0~1.0の間の値で指定することでバーの位置を変えることが出来ます。つまり現在値を最大値で除算することでそのままパーセンテージ表示に対応させることが出来ます。

バー表示だけでは情報が少ないのでテキストによる表示も追加してます。FormatText はテキスト内に引数を埋め込むことができ、変数を渡すことで引数をテキストに変換してくれます。



手順が前後しますが、プレイヤーキャラクタ側でイベントディスパッチャーを作成し、前述のEvent On Initialized内で作成した各更新イベントにバインドしています。

そうしておいて、プレイヤーキャラクタやアビリティーのイベントでスタミナや体力が変化した場合は、プレイヤーキャラクタ側で更新イベントを呼び出し、表示の更新をおこなわせています。

更新イベント

処理の末端でcallしている部分が(メールアイコンの付いているノード)がバインドされた更新イベントを呼んでいる箇所になります。

各処理でイベントを呼び出していたのですが、最終的にタイマーイベントの繰り返し処理の中でcallするようにしました。各種数値は別ファイルで管理しているので各所で消費したり増加した数値はそちらにまとめて書き込み、タイマーイベントの中でスタミナ等の自然回復をおこなっているので、それも含めてcallする更新処理内で管理ファイルから読みだした数値でUIの更新をおこなっています。



HUDを作る

ステータス表示用のウィジェットが出来たので、こんどはウィジェットを画面に表示するときに使うHUD用のコンテナウィジェットを用意します。

ゲームにおけるHUDはいってみればゲーム画面上にオーバーレイで表示されるUIのことです。

HUD用のコンテナウィジェットの仕組みは単純で全画面表示の CanvasPanel ウィジェットを置いているだけです。

HUD用のコンテナウィジェット



HUD用のコンテナ(CanvasPanel)の中にSizeBoxを置いてその中に先程作ったステータス表示用のウィジェットを置きます。

前述したようにウィジェットはサイズの指定ができません。その中でSizeBoxだけはサイズの指定ができる(むしろそれしかできない)ので、中に入れたウィジェットは幅、高さともにFillにしてSizeBoxいっぱいになるようにしておき、サイズボックス側でサイズを指定して編集時と同じサイズに調整します。

コンテナにしている CanvasPanel は自由な配置ができるウィジェットなので、大きさを決めたSizeBoxウィジェットを見やすい位置に配置すればHUDのデザインは完了です。



UI(HUD)を画面に表示する

作成したUIウィジェットの表示方法ですが、Create widget で、事前に作成したUI、この場合はステータス表示用のウィジェットを配置したHUD用のコンテナを準備します。

その後、AddToViewport で画面に表示させます。

UI(HUD)を画面に表示する

ちなみにAddToViewportでViewport(表示画面)に登録したウィジェットはRemoveFromParentで取り外すことが出来ます。

今回はHUDとしてステータスを常時画面に表示させるので、Removeせずそのまま使います。

ステータス表示




まだまだ細かい調整は必要(画面サイズによってはウィジェットが画面からはみ出たりする)ですが一応ステータスを表示させる目的は果たせました。

デザイン的に微妙なのは気にしない方向で(´・ω・`)



Post If you feel like it, I would be happy if you could post it.