以下の内容はhttps://limesode.hatenablog.com/entry/2025/09/13/161801より取得しました。


ゲージ100本ノック 98

ぷちコンの制作に集中してたので前回の記事から一か月も更新が止まってました。

今回もマテリアルインスタンスを使ったケースです。ゲージ自体はシンプルにバータイプで増減するだけ。このゲージの増減に連動するようにエフェクトを纏わせます。

ゲージをじっくり見てられないような忙しいゲームで効果が期待できます。

なんか変化があったけど増えた?減った?というのが視界の端で分かりやすくなります。

サンプルとしてプラスとマイナスにしたけど、マイナスのカタチがシンプルすぎてマイナスというよりただの棒に見えてしまう罠。1枚のテクスチャで2パターンを切り替える仕様なのでいろんな図形を試してみると何か発見があるかもしれません。

 

98. ゲージの増減でエフェクトを乗せる

この種の動きは普通ならエミッターを置いてパーティクルを飛ばしたり、プログラマにお願いしたりするかと思います。

表示時間は短めを想定しているので、あまりリッチなつくりはちょっともったいない気がします。まずは軽く作ってみて繰り返しが気になるようだったら、改めてプログラマに依頼するのでもいいかと。

 

ある程度散らばった状態で表示を開始したいので、マテリアルインスタンスで時差を作り、ランダムっぽく見えるようにパーツを配置します。

移動アニメーションはシェーダーで常に動いている状態にします。

 

テクスチャは 64x32px

タイリング設定は Clamp

これをV方向に動かすだけなのですが、表示するときには長方形にするので、スケールを調整する必要があります。

とりあえず今回は縦横のバランスを 1:3 にしました。

U方向は、テクスチャの半分を使うので、スケールは以下のようになります。

あとはTimerノードで 上下方向へ動かすのですが、スケールがかかっています。

見える範囲を端から端まで移動させるには -3.0 ~ 1.0 の範囲で移動するとよさそうです。

 

絵的にも方向もプラスとマイナスを切り替える必要があります。

この切り替えタイミングは、それほど頻繁ではないので、パラメータで受け取ることにします。

とりあえず動かすところまではこんな感じ。

図の下のほうにある ScalarParameterノードの Offset は、移動位置をずらして差をつける目的で追加しています。マテリアルインスタンスでバリエーションを出すのに利用。

 

プラスとマイナスを切り替えるときに、3つの値(上図の矢印)を一気に変更するので、VectorParmeterノードを使いたいところ。ただ、複数配置するマテリアルインスタンスたちに対して 一度に全部変更するとなると、前回同様パラメータコレクションを経由する方が簡単です。

というわけで ラメータコレクションを用意します。

RGBAとなっていますが、用途は自由。今回は

R: U方向のオフセット(0 だとテクスチャの左半分、 0.5 だと右半分)

G: V方向の移動 始点

B: V方向の移動 終点

A:全体のアルファ値

(アルファは最初から 0 にしていると、レイアウトしづらいので、今はいったん 1.0)

 

G と B の値を逆にすると移動方向が反転することになります。

ゲージが増減する際に、まずこのパラメータをセットするようにします。

 

これをマテリアルに組み込むとこうなります。

プレビューは正方形なので縦につぶれて表示されてます。

 

あとはここに、上下方向のグラデーションマスクを作って乗算します。

0.5を引いてAbsノードで絶対値にした状態では 0 ~ 0.5 のグラデーションで、さらに中央部が 0 になっています。

1-x(OneMinus)ノードを使わなくても SmoothStepノードでいい感じにできます。

SmoothStepノードは、 Max が 1.0 に、Min が 0 になるように計算して結果を返してくれます。こういう線対称なグラデーションは何かと使う機会が多いので覚えておくと重宝します。

 

このグラデと、バリエーション用の Opacityと、パラメータコレクションの Alpha をまとめて掛けると完成。

これをParentMaterial(親マテリアル)として、右クリックしてMaterialインスタンスをいくつか作って並べます。

 



チェックをつけると値を上書きすることができます。

チェックを外すと、マテリアル内の初期値が使われます。

 

透明度に変化をつけて少し重ねたり、スピードの近いものを離したりしながら、

いい感じに配置します。

 

マテリアルはこれで準備完了です。

あとは Widgetブループリントから表示タイミングやフェードをコントロールすればいいだけです。

 

 

ここからはテスト用のWidgetブループリントを用意して動かせるようにします。

 

適当なレイアウトです。

 

 

テクスチャの見た目と移動方向を切り替えるカスタムイベントがこちら。

動きは 上か下の2択なので、Boolean型の 入力ピンで方向を受け取ります。

勝手に決めますtrue で上! false で下!

右上の SetVectorParameterValueノードで マテリアルパラメータコレクションに書き込みます。

青色の ParameterValue ピンからドラッグして MakeColorノードを取り出したら、今度はのピンから SelectFloatノードを取り出します。

A は trueのとき 、B は falseのときに出力されます。

実装するときはプログラマに相談して決めるといいです。

 

このカスタムイベントをゲージが増減する直前に呼び出すようにします。

このときアルファ値を 1.0 にすることで 見た目に出現させています。

ということで、マテリアルパラメータコレクションのアルファ値はこのタイミングで 0を初期値にします。

 

 ここは UI制作の数ある闇のひとつでもあります。

誰が、どこのプロセスが、タイムラインが、最後の値をセットもしくは更新するのか。この辺のポリシーをあいまいにしたまま作っていると、意図通りに表示されなくて原因調査と対策に無駄な時間を使うことになったりするので恐ろしい。

 

実は

マテリアルパラメータが Vector型でひとつ余ったので、アルファフェード用にしましたが、Panel の中に入れてしまえば、Panel の Render Opacity でまとめてフェードがかけられます。

 

今回はVector型のパラメータを一部だけ書き換えの方法を紹介したかったのでマテリアルパラメータコレクション を使った アルファフェードで行きます。

 

ということで消す方法。

いったん Get して再び束ねて Set するかたちになります。

A だけそのままつながずに、0 を入力します。

Set ノードの Parameter Valueピンが選択して渡せるようにできたらいいのですが将来に期待しましょう。

Get ノードのほうは、Breakノードでバラしてもいいのですが、


ノードが増えるので、Split Struct Pinで分解します。

Set ノードのほうは、ParameterValueピンからドラッグすると Make Color ノードがすぐ見つかります。

 

この方法は、ある瞬間の値を部分的に加工したりと介入できるのでおすすめです。

 

ここまでに用意したもので、実装は可能ですが、キー入力してテストするところまで作っていきます。

 

まずゲージの増減する処理を、テクスチャの見た目と移動方向を切り替えるカスタムイベントの続きとして追加します。

拡大すると、

GaugeValue という Float型の変数を新しく作っています。

このカスタムイベントが呼ばれるたびに、0.01 ずつゲージを増やしたり減らしたりします。

 

 

次にアルファでフェードアウトするカスタムイベントを用意します。

AlphaValue という Float型の変数を新しく用意。フェード用に減らしていく使い方。

0 と同じかマイナスになったら、false になってフェードアウト終了。

 

0.02秒おきにこのカスタムイベントを呼び出します。

Set Timer by Eventノード の ReturnValue ピンから Promote to variable(変数に昇格)させておくと、タイマーを外から止めたりできるようになります。

AlphaValueの減らす量と、このタイマーの時間間隔を調整してフェードの印象を調整します。

 

Timeは ”秒” で指定するので、当面は 0.016秒より速くするのは注意が必要です。

コンソールゲームで快適とされるフレームレートが 60fpsです。処理負荷の状況に応じてフレーム更新タイミングがが可変というのも一般的になっています。 60fps は 1/60秒で描画が更新されます。それより速いと画面に反映されないタイミングでの計算が無駄になったり、更新回数の多さが、全体への負担になるので注意です。

 

ついでにこの部分、関数にしてみましょう。

下段のノード3つを選択してハイライトしたら、どれでもいいのでノードの上で右クリック。

コンテキストメニューCollapse to Function(関数化) というのがあるので選択。

関数のグラフが開くので、適当に命名。UpdateAlpha としました。

関数なので外からの値(引数)を受け取れるようにします。

この関数を使って、カスタムイベントを整理してみると、

すっきり。
コピペが簡単だとはいえ、関数化することで、同じ仕事をするノードのグループに名前を付けることになるので、見やすく、また流れがわかりやすくなります。変更や修正も1か所触るだけで済みます。なので同じ内容のノードのカタマリが複数現れたら、関数化を考えるといいですよ。

 

 

最後に、キー入力を受け付ける処理

キーを押している間はゲージが動くようにしたいので EventTick を活用します。

プロジェクトによっては Widgetブループリントで EventTick が無効にされている場合があります。つなぐことはできますが、コンパイルするとエラーになります。その場合  ProjectSettings で有効にします。ProjectSettingsが有効でEventTickノードが見つからない場合は、ClassDefault の 詳細設定 Performance > Tick Frequency が Never になっているかもしれません。Auto にするとコンパイルできるようになります。EventTickノードはほかのノード同様に検索で取り出せます。

 

よく簡易的なテストなんかでお世話になる Inputノードは、キーを押した時と離した時にそれぞれ 一度だけしか発火しません。

押したときにフラグを true にして、離したときにフラグを false にするようにしておいて、EventTick のところでそのフラグを判定して分岐するというのもありですが、判定するキー専用のBoolean型変数を用意しないといけないのがちょっとアレなので、今回は、PlayerController から Is Input Key Down Was Input Key Just Released  を使って検出します。

キーを離したときを検出するノードを探すとき、現在形と過去形になっているので、ちょっと雰囲気の違いに戸惑います。

UI関連でキー入力関連のワードはたいてい押したときは Down か Press、離したら Up か Release あたりを覚えておくと、いろんな開発環境で助けになると思います。

 

EventTick は毎フレーム駆動します。(確かWidgetブループリントのTick速度を変えられたと記憶していますが今回はテストなので)

EventTickが駆動したときに キーを押しているかどうか判定して true だったら false だったら、で条件分岐させます。テクスチャの見た目と移動方向を切り替えるカスタムイベントを呼び出しています。

押している間、何度も true になるので、何度もカスタムイベントが呼ばれます。

そして、その都度 Float型の変数から値が増減されるので、結果ゲージが動くことになります。

 

すでにフェードアウトが動いているかもしれないので、保険的にタイマーをクリアします。

Set Timer by Eventノードで タイマーをセットすると、彼は勤勉なので、途中で事態が変わっても動き続けます。なので 事前に変数化して用意しておいたTimer Handle を使って介入するのです。Clear and Invalidate Timer by Handle 以外にもいろいろ用意されています。

 

 

キー押している間は常にカスタムイベントが呼ばれ続けますが、指を離した次の Tickタイミングで Is Input Key Down の判定が falseでスルーされてきます。

ようやく Was Input Key Just Released が true になります。 

ということでフェードアウト開始。

 

指を離して一定時間後に、フェードアウトさせるために、以下の処理を追加。

前のフェード開始タイマーが、待機してるかもしれないので、ここでもTimerHandleを追加しておいて、強制的にクリア。

Set Timer by Event 便利なのでよく利用するのですが、タイマー発動中に不意に連続で呼ばれると表示タイミングがバグって見えることにつながるので、ハンドラーを用意してコントロールするのが重要です。ちょっと面倒に思うことがありますが、UIってほとんどがイベントドリブンなふるまいなので、タイミングの管理は必要経費だと思うことにしています。

 

 

 

これでテスト用のブループリントは完成です。

 

あとは適当なレベルブループリント作ったら Viewportに置いてプレイするだけです。

 

せっかくなのでデザインを変えてみました

 

 

ちょっと遅れて消えるようにしています。

ゲージの変化量と、視界の中に入りやすいかどうかで、この演出時間は加減するといいでしょう。

こういったプロトタイプを作ることで、手触りという経験値を手に入れることができるのです。実装を担当してくれるエンジニア、プログラマ?に自信をもって指定書を渡せるようになりますよ。

 

UIデザインが決まってから、オーダーを受けて作り始める場合、試行錯誤のスケジュールが組み込まれていないことがほとんどだと思います。一般にUI開発のスキルについて語られにくいのはこういった小さなマイクロインタラクションとどれだけ向き合ってきたかが定量化されていないのも理由としてあるのかなと、思ってみたり。

 

ということで今回は以上です

 

ただのゲージでも、いろいろな見せ方があるものですね。

残すところあと2本

どうなることやら

 

ではでは

素敵なゲージライフを!

 

 

 

 

 

 

 




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

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