以下の内容はhttps://limesode.hatenablog.com/entry/2024/12/30/013213より取得しました。


続 ゲージUI を試すためのプロジェクトを作る

前回の記事で振動するゲージを作りました。少し前にゲージをテストするためのプロジェクトを作ったので、そこに振動するゲージを組み込む流れを書こうと思います。

続きになるので、過去記事のリンクを貼っておきます。

 

limesode.hatenablog.com

エンジンのサンプルに手を加えます。ステージに置かれたキューブを撃つと体力ゲージが表示されるようにして、自分の考えた最強のゲージをテストできるようにしようというものです。

続きとして、ゲージがゼロになった時の処理を書きました。

limesode.hatenablog.com

 

ゲージが振動する場合、たいていはダメージを受けたときなど、ネガティブなイベントが発生した印象を与えます。まれに、エナジー的なものをチャージしたりしてバフがかかったときや、心臓の鼓動のような演出などでも振動する例を見たことがあります。

今回はダメージを受けた想定でプレイヤーの体力を減らします。ダメージ要因からダメージの通知を受け取って、体力を減らす計算をしてから、HUD経由でゲージに反映させます。

 

イメージ

下流から作るほうがスムーズなのでまずはゲージから始めます。

触るアセットが多いので、ボリュームが多いように思いますが、実際作ってみるとそれほどかからない印象。エンジンの操作よりも命名に悩んだ時間のほうが長いかも。

 

ゲージ本体

振動するゲージのマテリアルを用意します。

全体図はこんな感じ。

FinalColor につながる上半分はゲージの色を決める部分です。

今回用に一定量以下になったら点滅するようにしました。

 

ScreenPositionにつながるのは振動する部分です。前回の記事三角関数を使ったタイプ 63. を採用しています。

シェーダーはこんな感じです。

ブループリントからコントロールするために ScalarParameter を2つ使用します。

ひとつはゲージを増減させるための "Vital"

もうひとつは 振動の幅を制御する "Radius"

 

Vital につながる Step ノードの2つのうちがゲージが点滅する境界。

0.25 なので 25%切ったら点滅するカラーに切り替わります。

下が ゲージの増減を担当します。

 

ゲージのシェーダーは以上です。

 

 

Widget

次にゲージを表示するWidgetブループリントを作ります。

今回は画面に対して位置が固定なので Overlay ではなく Canvas Panel を使ってレイアウトします。Canvas Panel の下に Imageを配置。

 

アンカーは調整しやすいように中央下にしました。

Alignmentはパーツの中心位置を設定します。デフォルトは 0なので、左上が基点になります。今回のように画面中央に配置したい場合は 0.5 にするとパーツの中心が真ん中になるので、 Position XY (0, 0) にするだけでセンタリングできます。

画面端からいくらか離したいので Position Y を -80 としました。

 

配置できたら Imageを選択した状態で 振動するアニメーションを追加します ①

名前を OOPS にしました②

Trackを追加して ③

キャンバスに配置したImageパーツを選択

マテリアルのパラメータにアクセスするので +ボタンをクリック④

Brush. Brush Material を選択 ⑤

+Parameter ボタンを押して ⑥

ポップアップリストから マテリアルのパラメータ Radius を選択したら、右にある 0.0 をクリックして 適当な値に書き換え ⑦

その右端にある ⊕ ボタンをクリック ⑧

これでアニメーションのキーが打たれます。

 

アニメーションの最終位置に再生ヘッダを移動させ⑨

パラメータを 0 に書き換え ⑩

キーを追加します ⑪

これで再生ヘッダを動かしてみると振動具合が確認できます。

エディタ上ではスケールの補正が効かないので荒ぶってますね。

 

上のスクショはすでに詰めてしまってますが、

アニメーションの尺(長さ)は 初期状態で 5秒に設定されているので縮めておきます。

 

次にブループリントを編集するので、編集モードを Graph に切り替えます。

さっそくゲージのマテリアルを DynamicMaterialInstance にします。

 

カスタムイベントを用意します。

Float型のピンを一つ追加。 GaugeValue と命名

ここからゲージの長さを受け取ります。

 

このイベントでは振動のアニメーション再生と、ゲージの長さを更新します。


ゲージのWidgetブループリントは完成です。

コンパイルして問題なければ保存して閉じます。

 

このWidgetブループリントをMyHUD で表示してもらいます。

 

 

HUD

弾が当たった時に表示するゲージを追加した後に続けます。

CreateWidgetノードを取り出してClass を体力ゲージのWidgetブループリントに変更したら、変数化(Promote to Variable)して、Add to Viewport ノードに渡します。

Add to Viewport ノードは 右クリックで検索しても出てこないのでドラッグして検索します。

下のようにつないでも問題ないです。

 

ゲージを振動させるためにカスタムイベントを新しく追加します。

体力ゲージのWidgetブループリントの中のイベントを呼び出すようにします。

HUDはゲージの量を管理しないので左から右に流すだけになります。

HUDはこれで完成です。

コンパイルして問題なければ保存して閉じても大丈夫です。

 

 

 

さて そろそろ終盤

PlayerState

プレイヤーの体力を管理するためのブループリントを用意します。

PlayerState というブループリントクラスを利用します。

ゆくゆくはスパコンゲージやらデバフ表現も作ってみたくなるかもしれないので、このPlayerStateで管理します。

 

コンテンツブラウザで右クリック>ブループリントクラスを選択して、"playerstate"を検索します。

Selectボタンを押すとアセットが作られるので、MyPlayerState 命名

 

ここでもう一つ、ブループリントインターフェイスを使うことにします。

コンテンツブラウザで右クリック>Blueprints>Blueprint Interface を選択

IF_toPlayerState命名

ダブルクリックして編集ウィンドウを開くと、右のほうで関数名を入力してほしそうにしているので、関数名を決めてやります。

体力を減らす目的で使うので VitalDecrease と命名

"ダメージ量"を受け取りたいので、Inputsのピンを追加します②

型は Float ③

名前は DamageValue にしました。④

 

体力は整数のほうが管理しやすい場合もありますが、今回は割合を計算したりするので Float(浮動小数)で進めます。

 

コンパイルボタンを押して問題なければ保存して閉じます。

 

次は MyPlayerState を編集します。

編集ウィンドウが開いたら タブのすぐ下にある Class Settings をクリックします。

右の Detailsパネルの真ん中くらいにある Interfaces のところにある Add ボタンをクリック

プルダウンリストがポップアップするので、さきほど作ったブループリントインターフェイスを検索します。おそらく "IF_" の文字列を入力するとすぐに出てくると思います。

No Interfaces のところが選択したやつに変わります。

 

編集先を Viewport から Construction Script に切り替えます

 

エディタ左の MyBlueprint パネルに VARIABLES の項目があるので

プラスボタンをクリックして Float型の変数を2つ追加します。

現在の体力を CurrentPlayerVital

最大体力を MaxPlayerVital 命名します。

 

この変数を Set の形でグラフにドロップしたら、

紫色の Construction Script ノードが一つ置かれているので、ここにつなぎます。

とりあえずMaxPlayerVital は 12000 としておきましょうか。

このコンストラクションスクリプトでは、変数などの初期状態を管理します。

 

次に編集先を Construction Script から Event Graph に切り替えます。

 

まずはHUDをがっちり掴んでおきます。

HUDもBPインターフェイスを利用できるので、利用するとキャストの必要がなくなります。また「ゆるいしがらみ」でアクセスできるのでメンテしやすくなります。

今回は変更範囲が増えるのでまたいずれ。

 

次にエディタ左の MyBlueprint パネルに INTERFACES の項目があるので見てみると、ClassSettings でセットしたブループリントインターフェイスの関数が追加されています。

これをダブルクリックすると、グラフにノードが出現します。

右上にあるのが、BPインターフェイスを示すアイコン。

 

ちなみにこの黄色いアイコンはイベントであることを示しています。

BPインターフェイスを編集して関数を登録するのですが Outputs の有無で変化します。

Outputs は戻り値(Return Value)と言ったりしますが関数内で処理した結果を別のところで利用したいときに追加して利用します。

アンリアルエンジンでは、戻り値があると 関数(Function) 、戻り値が無いと イベントとして扱うのが仕様になってます。

で、戻り値であるところの Outputs を追加すると、黄色いアイコンが グレーになります。

ダブルクリックしてみると下のように関数専用のグラフになります。

今回は結果を求めない投げっぱなしの処理なので、イベントで扱います。

 

BPインターフェイスで事前登録したイベントまたは関数は中身がありません。

例えるなら BPインターフェイスは道案内の看板みたいなものです。

 

中身は

ダメージ量を受け取って、

CurrentPlayerVitalから引き算(この段階でまだ試算)

まだ残っていたら(0以上だったら)CurrentPlayerVital からダメージを差し引く。

MaxPlayerVital で割るとゲージの長さが確定するので HUDのイベントに渡す。

引き算して CurrentPlayerVital がゼロ以下になったら、マイナスにならないように 強制的に 0 を入れて HUDのイベントに渡しています。以降は 0以下にはならないようにしています。プレイヤーの死亡演出を加えるならこの分岐を利用します。今回は振動をテストするだけなので、この辺までにします。

 

コンパイルして問題なければ保存して閉じます。

 

 

GameModeに登録

MyHUD を登録したときと同じ要領で、PlayerStateも登録します。

セットしたらコンパイルして保存したら閉じます。

 

 
ダメージ通知

今回 ステージに置いてある青キューブをダメージソースにします。

今の青キューブは繊細過ぎて何が当たっても青キューブがダメージを受ける仕様なので、判定を加えます。

間にBranchノードを挿入します。

OnComponentHitノードから何が当たったかを取り出せるので、それを判定します。

Other Actorのピンからドラッグして Get Classノードを取り出します。

このピンからは当たったオブジェクトがわかるようになってるのですが、そのままだとA=Bのような判定ができないので、Class 名で判定します。

半角の "" で検索します。

出てきた Equalノードの SelectClassをクリックして検索フォームから "projectile" を入力します。

このエンジンのサンプルで使われている弾は BP_FirstPersonProjectile というアセットが射出されているので、BP_FirstPersonProjectile を選択します。

これで、青キューブは黄色い球だけにダメージを受けるようになりました。
球以外はこちら

Branchノード の Falseピンから PlayerStateのイベントを呼び出します。

PlayerStateにアクセスするために Get Player State ノードが用意されています。

 

PlayerStateはBPインターフェイスが設定されているので、

リストアップされるものに (Message) が付加されています。これが目印。

ノードを取り出すと封書が開かれた状態のアイコンがノードの右上につきます。

 

BPインターフェイスを使っていない場合は、キャストが必要になります。

 

BPインターフェイスを使うと、キャストが不要になります。

以降いろんなアセットでプレイヤーを痛めつけたり、バフを与えたりすると思いますが、この GetPlayerStateノード経由で MyPlayerState のイベントを呼びだせるので、MyPlayerState の存在を忘れてしまっても大丈夫です。 まぁ一人で全部編集してるので忘れることはなさそうですが。

 

編集は以上です。

コンパイルして問題なければ保存してテストしてみましょう。



青キューブに接触したタイミングでゲージが震えて減ったら完成。

おつかれさまでした。

 

続きということで、過去記事と同様の操作についていくらか端折っています。

記事について解りにくいところなどありましたらコメントいただけると、コメントで返信するか説明を本文に追記するかしますのでお気軽にどうぞ。

 

晦日も押し迫ってきました。

今年も多くの方にアクセスいただきまして本当にありがたい限りです。

ブログを続ける燃料になっています。

今年は前半が忙しすぎたので、一時、長いブランクがありましたが、ゲージを100本つくるなどの暴挙に出て今に至ります。きっかけがなくなると途端に書かなくなるので100本目を書き上げるまでは頑張ろうと思います。年を越してしまいますが、アンリアルエンジンが 6 になるまでには必ず。何とかして終わらせます。

 

ではでは

来年もよろしくお願いいたします

素敵なゲージライフを!

 

 

最後に

今回の実装をどう進めるかで少し悩みました。

UIの見た目を作って楽しむだけなら、「動けばええやん」で極力手数を少なくする方向でいいかと思うのだけど、プレイヤーの体力をゲージで動かすためには、その状態を管理する存在が必要で、その管理をHUDや、ゲージのブループリントが行うのはよろしくないなとか、とはいえ表題のとおりゲージUIを試すことができればOKなのでは?と割り切らないと中途半端になるよね、などと考え始めてしまい、年末の締めスケジュールもあってなかなか進まなかったりしましたが、なんとか上記の構成に落ち着きました。

改めて記事の行方的にシェーダーの習得とゲージ研究の助けになることをまずは基本方針として書いていくことにします。現場で頑張っているUIアーティストを陰ながら応援できればいいなと考えています。

ちゃんとしたゲームを作りたい方にはをオススメしておきます。




以上の内容はhttps://limesode.hatenablog.com/entry/2024/12/30/013213より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14