以下の内容はhttps://limesode.hatenablog.com/entry/2025/11/08/190045より取得しました。


ゲージ100本ノック 100 《タネアカシ編》

なんとなく今まで紹介してきた方法を思い出しながら挑戦してみてほしいなと、ふと魔が差してしまい、前回の記事では見た目に盛り合わせた要素をヒントと称して軽く説明するにとどめました。

今更タネというほどもったいぶるようなテクニックがあるわけではないですが、どうやってるのか、というのを書いていきます。シェーダー(UEで言うところのマテリアル)は、作って動かした方が面白いので、ブループリントでチャージするカスタムイベントを作ったり、キーボードでゲージを増減させたりしてます。

パラメータがちゃんと想定通りの動きをするかを確認するのが目的ですので、実装にはあまり参考にならないものもありますが、その辺はご理解いただけると助かります。

マテリアルさえちゃんと動いているのを確認できれば、そのままアセットを正式な場所に持って行けばいいだけですし。

 

ではさっそく

 

100. ゲージ

まずは今回の動き

5種類の要素について説明していきます。

目コピチャレンジの答え合わせになればと思います。

 

 

体力ゲージ

パーツの構成については前回の記事で書いています。

メインのHPゲージなので、よくある2段階式にしました。→ 77.

ゲージの形状をテクスチャのアルファチャンネルで、カラーはシェーダーで着色。

テクスチャがアトラスなので、一部分を切り出すために VectorParameter を使っています。



 

ゲージが増えるときにのオーバレイエフェクトは、ゲージの着色部分で黄色の部分に適用します。

Timeで常に動かしています。模様のカラーがゲージと同じだと単色に見えます。

 

その模様のカラーを白色にすると目に見えるようになります。

黄色のゲージカラーと白色は、パラメータでブレンド量が調整できるようにしてあります。

白色は、Lerpノードの B のピンに入力してある 1.0 です。

タイミングが来たら一定時間フェードするようにブループリントから制御します。

 

タイムライン アニメーションを使ってもいいですが、ブループリントでフェードする方法を紹介します。

 

Float型の変数を 1つ用意して、初期値を 1.0 にして、徐々に減らしていくカスタムイベント。ゼロになったら終了します。

Set Timer by Eventノードは一定間隔で朱色のラインでつないだイベントを呼び出します。条件が外れるまで、再び自身を呼び出す形になっています。

このスタイルは個人的にテンプレートになってる感じで、タイムラインを使わないときはこのかたちが多いです。

 

加算する場合は 満タン かどうかを判定して、減算する場合は 0 かどうかを判定します。

スピードは、加減算の変化量と、Set TImer by Eventノードの Time で間隔を調整します。

 

 

 

 

数値

数字の動かし方は前回の記事で書いたので、今回はカーブさせる方法について。

当初Photoshopでグラデーション作って試してみたら、やはり精度の点で解像度どビット深度の調整でコスパの悪さが気になったので、エンジンのカーブアトラスを採用しました。

上図はPhotoshopで無理やり変形したので妙に歪んでますが、理屈としては、テクスチャUVのU座標に対してカーブするようにV方向をずらしていきます。

3桁とも横幅が同じなのに、傾斜が緩くなるとスリムに見えます。脳が無意識に奥行き感を補間してしまうのが原因だと思う。

傾斜の程度に合わせて、横幅の調整をすると違和感は減ると思います。(調整をさぼった言い訳)

 

まずは カーブアセットを作成します。

コンテンツブラウザで右クリックすると、Miscllneous というのがあるので中にあるCurve を選択します。  

今回レイアウトした数字の桁は 3桁カーブクラスは LinearColor を選択します。

Vectorでも問題はないのですが、ピクセルのずらす方向が+方向のみなのでマイナスの値が無いほうが扱いやすいと思い LinearColor にしました。

中のFloatが 4つあるので将来的に数字の桁が増えても 4桁まではカーブアセットを増やさなくても対応可能。

 

編集します

RGBAをそれぞれ、100の位、10の位、1の位と決めて、何となく曲げてみます。Aは予備。

アナログなやり方ですが、後ほどマテリアルに組み込んでから表示されたものを確認しながら微調整するので、最初は適当に進めます。

保存して、今度はカーブアトラスを作成します。

これも Miscllneous の中にあります。

編集ウィンドウを開いて、Gradient Curves のところに先に作ったカーブアセットをセットします。

ここにカーブアセットをセットします。複数あればそのたびに追加していきます。

このカーブアトラスは、カーブの内容をテクスチャにして書き出す仕様ですので、解像度があります。大きいほうが精度が高いものになりますが、そのぶんVRAMの使用量も大きくなるため、サイズを節約して切り詰めます。

Square Resolution のチェックを外すと Height が変更できるようになるので、まずは高さを切り詰めます。

今回のゲージでは 2つのカーブアトラスを使用したので、Heightは 2 にしてみたらResourceSizeがかなり小さくなりました。

 

カーブが準備できたので、マテリアルを用意します。

 

完成形

 

数字はテクスチャ内で水平に並んでいるので、1文字ぶんのスケールをかけて U方向にずらせば狙った数字が切り出せます。

タイリングしないように Clampです。

 

この数字のマテリアルは専用の表示になるので、ひとまず汎用性は考えないことにして、U座標に掛けるスケールについては、Constant ノードにしています。

 

数字ひとつのサイズは 32 x 128px 、テクスチャ解像度が 512px、

U方向に 32 / 5120.0625 ずつ並んでいます。

Constant ノードは 数字キーの [1] を押しながらクリックすると取り出せます。

 

Scalarパラメータの Index で 0 ~ 9.0 を受け取る前提で考えます。

その値に、1文字ぶん の定数 0.0625 を掛けると0~9の各数字のU座標になります。

 

V方向は、カーブによって変形させます。

CurveAtlasRowParameter ノードを利用します。

このノードに、カーブとカーブアトラスをセットします。

 

カーブで作ったグラデーションは水平方向でアトラス化されているので、

CurveTime ピンには TexCoordComponentMaskR をつなぎます。

CurveAtlasRowParameterノードの出力は LinearColor ということで Vector4 の状態。RGBA それぞれ 100の位、10の位、1の位なので、選んで個別に取り出すことはできるけど、じゃあ 一本ずつ取り出したバージョンのマテリアルを3つ作るのか、というとさすがに効率が悪いので、マテリアルインスタンスで運用します。そうすると、3桁分の数字に対してパラメータで切り替えればいいのです。

 

そこで ドット積(Dot Product)を使います。

Dotノードを使うとチャンネルマスクのような使い方ができます。

ドット積は 2つのVector4 を掛けて足し合わせるので、結果的に 4つのFloatが 1つに収束します。

このとき、 ゼロのあるところは掛け算で消滅します。この性質を利用します。

 

残したいチャンネルに 1 を、他のチャンネルを 0 にした Vector4パラメータ を用意してカーブから出てくる Vector4 にぶつけます。

 

例えば、Greenを残す場合 

 ( ↑マテリアルインスタンスで入力した状態 )

パラメータで切り替えられるようなったので、マテリアルインスタンスからでも狙ったチャンネルに絞ることができるようになります。

 

あとは、カーブの強さを調整できるようにして ScalarParameterノードを乗算しておきます。値が微妙な時に一気にブーストしたり繊細にしたりできるので便利です。無くても問題ないです。初期値に 1.0 を入れておくと、結果に影響しなくなるのもポイント。

今回はカーブの値の範囲を0~1.0 で作ったので 初期値を 0.1にしています。 

これを数字テクスチャの V座標から引き算(Subtract)します。

カーブは 正の値で作ったので、引き算することで、U座標に対する V座標が負の領域になります。(下図左)

画面に表示する際、四角形に収めようとするので、負の座標からサンプリングすると、結果的にピクセルが ↓ 方向にずれます。マイナスぶんがぐいっと押し出される感じ。

(下図右)

 

 

今回数字のために用意したマテリアルは以下。

左から、親マテリアル、100の位、10の位、1の位 

 

マテリアルインスタンスをレイアウトします。

カーブの具合を調整して整えます。

ちょっと横幅もいじってみたら、違和感がマシになりました。




レベルメータ風謎のチャージゲージ

一定の速度で溜まっていきます。使用したり戦闘不能になったりすると、ゼロに戻ります。
ゲージの形状がカーブしているのと刻みが不定なデザインを採用したので、均等で直線で進むゲージ 13. は使えない。そこで、グラデーションを自前で用意する方式を採用。

 

シェーダーではゲージのシルエットと、グラデーションという 2つのパーツを組み合わせています。

固有のゲージなので、汎用性は考えないことにして、テクスチャアトラスからUVを切り出すのに、Constant と、 Constatnt2Vector ノードで値を指定し計算しています。

 

ゲージの増減は、シンプルに グラデーションテクスチャに対してStepノードを使うだけ。

グレースケールの段階を均等に割ってブラシで塗って作るので、それなりの手間がかかってます。

(ゲージの外は雑でもバレない)

0 の黒を使うと、ゲージが空っぽにならないので、一番下は 0 以上のグレーにするのがコツ。

 

ゲージのカラーに カーブアトラスを使用しました。

0.3(30%)を越えるとオレンジから緑になる想定。

数字と同じカーブアトラスにセットしています。

事前に用意したカラーでゲージの色を変化させます。

15. と同じ要領でゲージ残量を CurveTime に適用します。

 

数字はときはカーブの全域を取り出して使いましたが、これは カーブの一部分を取り出して使うので、ゲージ量の ScalarParameterノードを直につなぎます。

 

 

 

チャージ式のお花アイコン

円グラフの動きは 12. で 2枚の絵が切り替わるのは 47-54. です。

 

お気づきの方もいらっしゃるかもしれないですね。

今回開始位置を90度回すのに、12. とは違うつなぎ方をしています。

符号は同じですが範囲が違います。

VectorToRadialValueノードが出力する、Vector Converted to Angle については、角度を数値化しているので、符号の向きが同じなら結果も同じになります。

 

実は最近気づきました。UV空間の値を渡すので、0.5なんて半端だ! という思い込みがあったのようです。なので、今回少しノードのつなぎ方変わっているのです。

思い込みは新たな途を切り拓くときの壁になるので気をつけないといけませんね。

 

V1-x ノードで 1 → 0 に変えつつ、UVを入れ替えて、-0.5 すると、UV空間が90度回転します。

円グラフタイプのゲージが完成。

絵柄をハートにすると「ゼルダのやつ!」とか言われるので注意が必要です。

 

 

ゲージが満タンになったときに、2タイプのエフェクトを表示しています。

テクスチャは右端にあります。

基本はゲージ 69. で紹介した方法です。

この時はテクスチャの左上が UVの 原点だったので、作り易かったと思います。

 

今回のはこのようにしました。

UVを -0.5 してすぐに Absをつないでいます。そのあとで切り出すための計算をします。

69.では 2を掛けて 0 ~ 1 にしていましたが、どうせスケールを掛けるので、0 ~ 0.5 のままにしています。

 

テクスチャアトラスはこのようになっています。

 

切り出したいパーツの横のサイズは 64px、テクスチャ解像度の横方向のサイズは 512px

ということで、U空間に掛ける値は  64 / 512 = 0.125 、V空間に掛ける値は 64 / 64 = 1

 

上にも書いた通りUV空間を 0 ~ 0.5 のままにしているので、ここで 2倍の値で掛け算することで帳尻を合わせます。0.125 → 0.25 で、 1.0 → 2.0 にします。

Offsetの値は、そのままの倍率で構わないので、U方向は 448 / 512 = 0.875

ScaleUV と OffsetUV を VectorParameterでまとめました。

結果オーライで、計算処理は少ないほうがお得です。

 

ここで、気を付けたいのが、テクスチャのバイリニア対策。

1px はみ出させてあります。

タイリング設定の Clamp と同じ効果を狙っています。

テクスチャアトラスをレイアウトするとき、切り出すサイズより1px 余分に残してマスクしています。99. の記事でUV範囲の内側に 1px 余白を、と書きましたがさっそく例外です。切り出す範囲の端まで絵があることが理由です。

Clampはテクスチャの端に効果がありますが、中は効果がないので、わざわざ手で対策してやることになります。

これでスキマが開くことなくキレイにつながります。

ただし、境界の位置が 4で割り切れない場合は、圧縮のダメージを覚悟する必要があります。色数が少なければ意外と大丈夫だったりします。

 

アニメーションについては、タイムラインで付けました。

拡大しながらフェードアウトしていきます。

 

 

満タンエフェクトのループする方は、ちょっとだけ小技を使っています。

中心から広がる動きは前回の記事で書きました。極座標で動かしています。

で、小技というのはこれ。

同じものが並ぶと、複製している感が出て安く見えてしまいます。そこで
WidgetがViewportに置かれたときに、初期状態の角度をランダムに変化させています。

 

このチャージ式のお花のアイコンは、1つずつ順番にチャージします。

チャージ完了時に通知するように、イベントディスパッチャーを追加しました。

 

チャージ完了時に呼び出すようにします。

 

親のWidgetブループリントのほうで事前にバインド(Bind)しておけば、通知を受け取ってくれるので、2つ目のチャージを開始できます。

 

Widgetお花1号! チャージを開始せよ。 お花1号 は完了したら通知するように。

・・・

お花1号: 完了しました!

Widgetでは お花2号! チャージを開始せよ。お花1号バインド解除。

      お花2号 は完了したら通知するように。

・・・

お花2号: 完了しました!

Widgetお花2号バインド解除。

 

というストーリーがこちら

Widgetでこのように構成しました。バインドは親から子に対して行います。子はイベントディスパッチャー作って呼び出すだけです。

 

今回見た目に動いていればよいということで、作り易さからチャージ処理を 子Widgetに丸投げしました。しかも、お花アイコンとエフェクトを一緒にしてしまったばっかりに、1つ目の満タンエフェクトの上(手前)に 2つ目が乗ってしまう結果になっています。

本当はチャージ用のお花アイコンとエフェクトは別々にしないといけないですね。

 

 

 

キャラ

キャラは特に難しいことはしていません。

テクスチャアトラスが長方形で、水平に 2種類が絵が並んでいるだけ。

 

U座標へのオフセットを ScalarParameterノードで切り替えられるようにします。

キャラは他にもたくさんいる想定で、テクスチャサンプラーはパラメータにしました。

体力がゼロになったときの演出として、 Dotノード(DotProduct)で一旦モノクロにして着色したカラーを Lerpノードでフェードできるようにしています。

 

モノクロ化は、NTSC加重平均法 というやつを採用しました。

固定の値なので、Constant3Vectorノードで
 X  0.298912

 Y  0.586611

 Z  0.114478

をテクスチャのカラーとドット積を使って合成するといい感じのモノクロにできます。

ただモノクロにしただけだとちょっと明るいので、

明度を下げて若干ヤバ味を足す感じで くすんだ退紅色を掛け算しました。

 

ダメージを受けた時の振動は、Widgetブループリントで揺らしています。

絵の内容によっては、テクスチャの解像度いっぱいまでピクセルがあるかもしれないので、シェーダーで動かすのはコスパが悪いというのが理由。

揺らすための余白が必要で、画面の描画領域がテクスチャ解像度より大きくとるか、余白を入れて絵を小さくするか、どちらにせよ透明部分も描画処理されるので、無理はしないほうがいいという判断です。

 

このカスタムイベントは、何かの値を判定して終了というのは無く、ずっと動き続けるので、止めるにはタイマーハンドラを介して止めます。

 

汗表現は、2パターンの絵を一定間隔で切り替えています。

シェーダーの Time ノードの値を加工して 0 1 の 2値にします。

そこにU座標へのオフセット量をかけてやると、パカパカするU座標が得られます。

 

パターンのサイズは 80px テクスチャ解像度は 256px

80 / 256 = 0.3125

2パターンの点滅ができました。

 

 

 

ここまでで、各要素の構造を紹介できたと思います。

最後に、キー入力の判定部分を紹介します。

簡易的なテストはレベルブループリントで、Inputノードを使うことが

キーボードの[D] で「ダメージ」、となりの[F]キー で「回復」 のカスタムイベントを呼び出すようになっています。

ダメージは毎回 60~180 の範囲でランダムな値になるようにしています。

Andノードを使って、ゲージがゼロ以上かどうかも判定に加えています。

 

 

 

今回はここまでにしておきます。

体力ゲージがゼロになったあとの処理とか、遅れて追いつくように減らす処理とかは下図で説明に替えられたら助かるのですが・・・

メインはこんな感じです。あとお花のWidgetもあります。

この100本目のアセットだけ切り出して公開も考えてみようかな。いや、いっそのこと全部公開する?

 

 

最後に

100本目でラストということで 盛り合わせてみましたが、いかがだったでしょうか?

総集編的な位置づけで、いつもより駆け足気味な感じになっているかと思います。

ひとまずUIで扱えると役に立つと思われる範囲で、ゲージ制作に絡めたシェーダーの紹介をしてきました。途中ネタが尽きて弱音を吐いたり醜態を晒しましたが、無事走り切れました。

Xでイイネやリポストしてくださった方々、ネタを提供してくださった皆様、本当にありがとうございます。とても励みになりました。今でも本当に100本も作ったのか?どこか番号飛ばしてるんじゃないか? と不安になります。

UIを制作している方で、シェーダーを覚えたいけどどうしたら?というお悩みに貢献できたら幸いです。

実際に100本作ってみましたよ~という方から感謝の言葉をもらう未来を夢想しながらこの企画は終了したいと思います。

そのうち急に思いついて番外編とかおまけ企画とかやるかもしれません。

まだまだわからん、とか他にも取り上げてほしいものとかあればコメントとかで教えていただけますと有難いです。

決して読みやすいとは言えない内容だったと思いますが、お付き合いくださった皆様ありがとうございました。

 

ではでは

ステキなゲージライフを!

 

 

 

 

 

 

 

 

 



 

 

 




 

 

 

 

 




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

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