~~~~~~~~~なみなみです
ゲージをゆらゆらと波のように揺らすやつ。スプラトゥーンで見かけた方も多いかと。最近ゼンレスゾーンゼロの体力ゲージで見かけました。これ先端部分に揺らぎがあるので、残り僅かになるとあとどれくらいかがわかりにくくなりますが、その辺は工夫すれば解決はできそうです。
波の動きについては、ちゃんと揺らすとコスパが悪いので疑似的に表現します。
理屈は
縦向き、UV空間でいうところの V方向に波形が繰り返し描かれているとして、その一部を取り出すというもの。

ループアニメーションさせると波打っているように見えそうです。
U方向はゲージの長さを表現するためにパラメータで制御します。
波型は、繰り返して使いやすいサインカーブを使います。
今回 3つのゲージを紹介しますが、見た目は同じでも作り方が変わります。
ゲームの負荷状況やメモリ使用量を考慮して選択できればデザインが維持できます。
41. 42. 43. 波のように揺れるやつ

まずはシェーダーでサインを扱ってみます。Sineノードが用意されているので以下のようにつないでテストすると、

TexCoordの V をSineノードに渡すと縦方向にグラデーションが現れます。
Sineの返す値は ±1.0 で、RGB値の範囲は 0~1.0
上図では適当にオレンジ色を足してますが、範囲を超えた部分のカラーがおかしくなっているのがわかります。

サインに渡す値は普通はラジアンで、1ループが 2π になるのですが、UEでは 0~1.0 を渡すと 2π ぶんの波形を出してくれるようです。数学の成績の芳しくなかった自分は楽させてもらってますが、甘やかされてるのがわかってちょっと不安になります。
Sineの返す値は ±1.0なので、調整します。
0.5倍して0.5足すと 0~1.0の範囲に収めることができます。


まだ波にはなっていないので、ここに U方向値を加味します。


SmoothStepでクッキリさせます。


やっと波形ぽくなりました。あとは調整できるようにしてゲージになるようにすれば。

パラメータは4つ
ScaleU ・・・ 波の大きさ(高さ)調整用
ScaleV ・・・ 波の周期(幅)調整用
Speed ・・・ 移動速度
Value ・・・ ゲージの長さ ※
ゲージの長さについては、0~1.0 では思うところに落ち着かないと思うのであとで少し捕捉します。
次は 42. です
三角関数での計算処理をGPUにやらせるのもったいなくない?ということで、最初からサインカーブをテクスチャにしておけばよさそう。ということでテクスチャを用意して動かしてみました。
128x128px

いままでのゲージタイプで使ったシェーダーで応用できますが、見た目を制御するためにパラメータノードをいくつかつないでいるので、ちょっとややこしい感じになってます。
テクスチャはインポートしたらタイリングの方向について設定を変えるのがコツ。

Photoshopで適当にシェイプを作って試してみたら、なんかそれっぽくはなったけど、あまりキレイなカーブじゃなかったので、ネットでサインカーブの説明してる記事をみつけて、そこのグラフ画像をトレースしたら、とてもきれいなカーブになったので、やっぱりちゃんと計算しよう、ということになりました。
以前の記事で紹介した Processing のお出ましです。
スクリプトは以下
void setup(){
// キャンバスサイズ
size(512, 512);
// 背景色
background(0, 0, 0);
// 1回だけのDraw
noLoop();
// スムージング無効
noSmooth();
}
void draw(){
float a,c; //角度とカラー
int y; //描く座標
float w = float(width - 8);
stroke(255, 255, 255);
for(y=0;y<height;y++){
a = (float(y) / float(height)) * TWO_PI;
c = cos(a);
c = c * 0.5 + 0.5;
line(0, y, 3+round(c * w), y);
}
save("image00_c.png"); // 書き出すファイル名
}
アンチエイリアスを期待してPhotoshopで縮小するので、わざと大きいサイズ(512x512)で描画しています。タイリング設定を Clamp にして使うので、左右については、余白を空けるようにしてあります。
float w = float(width - 8);
の 8 と
line(0, y, 3+round(c * w), y);
の 3 です。
4だと 1pixelずれたので、3にしました。これで左右に 4px の余白ができます。
Photoshopで動かしてもよかったかも。
サインカーブ言うておきながら、スクリプトではコサインを使ぅてます。
サインもコサインも波形は同じで、開始位置が違うだけです。タイリングするので、上下の端が同じピクセルになっていたほうが圧縮後にキレイにつながる感じがします。
noSmooth() を外そうかと思ったけど、ラインを斜めに描画するわけでもなく、真横に1本ずつ下に向かって描くので、期待するほどのアンチエイリアス効果はなかった。
なので、キャンバスを大きくして Photoshop の バイキュービック ではなく バイリニアフィルタを使って 128x128 に縮小しました。

バイリニアは、妙な補正が入らないので、ノイズが乗らないのがウリ。
Adobeさん Photoshop に サインカーブをシェイプでプリセット登録してくれませんかね。
次は 43. です
サインカーブをシェーダーで作ったら、こんな感じのグラデがあればOKでした

ということは、これもテクスチャに置き換えできそうな気がする。
![]()
4x128px のテクスチャを用意して試しました。タイリングは両方 Wrap のままでOK。

テクスチャの内容的に U方向の値は何でもいいので適当な固定値でも影響なし。

以上3タイプをまとめて紹介しました。
最後に、
パラメータについて補足しておきます。
Value はゲームシステムから受け取るパラメータです。
ゲームシステム的にゲージの増減は 0~1.0 が管理しやすいので、
Lerpノードを使って、シェーダーの値を都合よく調整します。

ゲージの見た目に上限と下限の都合のいい値を決めたら、それぞれ Lerpノードにセットします。
プレイヤーに誤解を与えないように慎重に調整します。
まだ残ってるやんけ! とか 満タンにならんゾ! とかは避けないといけません。
ScaleU と ScaleV を大きくすると下のようになります。

ダメージを受けた時だけ一瞬だけこうした変化をさせると面白そうです。
ScaleUだけを小さく(42. は逆に大きく)するとフラットに近づきます。

横を満タンや空っぽに近づくとフラットにしてもいいかもしれません。
体力ゲージだったら、普段フラット気味にしておいて変化があるとしばらくは波打ってるとか、プレイヤーが走ってる間だけとか、ちょっとしたきっかけに連動するだけで、凝った印象を与えられるかもしれません。

こういったところから、自分なりの演出を思いついてシェーダーに反映できるようになるとどんどん楽しくなってきますよ。
今回ちょっとアレルギーが出る方がおられるかもしれませんね。
でもこれを機に さいんこさいんにちょっとずつ慣れていってもらえればいいかと思います。
ではでは
ステキなゲージライフを!