いやぁレーダーチャートですよ。ゲームのUI作ってると、避けて通るのが難しいというか、ヘタに避けると事故るというか、かといって簡単には実装させてくれないというツンなところが憎いレーダーチャート。ステータス画面でキャラの成長度合いや武装なんかの性能差をパラメータ表示する際に使われることが多い印象。
ポリゴンメッシュのような柔軟な形状変化は、半透明テクスチャベースでの2D表現ではほぼ無理(直線の組み合わせなので頑張ればできますが、なり力技で無駄なパーツも増える)だし、プログラマさんへの負担がかなり高いのもレーダーチャートです。なのでプログラマさんの顔色伺いながらデザイン提案してきました。
かねてからレーダーチャートを自力で作ってみたくて、思いついたアイデアを実践してみたのが今回つぶやいたやつです。
ふと思いついたので6角形のメッシュに頂点カラーをつけてそれぞれをパラメータとLocalPositionとで計算してみたら、それっぽくできた。さすがに需要ないだろうなこんなつくり・・・ #UE4 #UE4Study pic.twitter.com/cXD79LovLb
— みつまめ杏仁 (@MMAn_nin) 2021年3月26日
たまたま思ってた感じに動作してくれたので、メモしておきます。
三角関数とかベクトルとかそういった計算は一切使ってません。
主に掛け算と引き算です。
さすがに こんな変則的な作り方が採用されることはないと思いますが、参考になれば幸いです。
blenderでメッシュを用意する
Verは 2.92 です。大したことしないので旧いVerでも他のDCCツールでも問題ないです。まず円錐を作ります。6角錐でも5角錐でもOK。底面は不要。
スケール をゼロにしてぺちゃんこにつぶしたら、スケールを「適用」して 1.0 に戻す。
[ObjectMode] モード Object → Apply → Scale
この時 底面が残っていると、ポリゴンが重なってしまって作業しづらくなる。
(ぼくはこの後 X軸を 90度回して Apply します。)
[Vertex Paint] モードにして 頂点カラーをつける。
このとき 中途半端な値にならないようにしっかり塗る。
色の順番は法則とかないので適当でも大丈夫。
ただし中央は動かないので 黒(0,0,0)または白(1,1,1)推奨。
色がついたら、FBXで書き出し。
(今回 FBXのバージョンとかはデフォルト設定のまま)
正面方向と上方向の軸に注意。インポートしてみて向きがおかしかったらモデルを回転させるか、FBXの書き出しで対応するかどちらかで。この辺は、作業のやりやすさと、エンジンにインポート後の配置のしやすさを考慮すると自然と決まってくる。はず。
UE4でのインポート時のダイアログで、
Vertex Color Import Option を Replace に変更する。
マテリアルの設定は
探さない、作らない、読み込ませない の3無い運動で。
無事インポートできら材料は揃ったので、次はマテリアルをどうにかすればほぼ完成。
新しくマテリアルを作成したら、
ShadingModel は Unlit(光源計算なし)を選択。
まず VertexColor をつなぎます。
プレビュー用のメッシュを登録すると作業がはかどります。
できあがった全体図
まずは頂点カラーを取り出すところ
各頂点のカラーから、ある数字を取り出すのにカスタムノードを使用。
中身こんな状態。
Codeのところは
return float((Red * 4) + (Green * 2) + Blue);
Red, Green, Blue は下の Inputsのところで設定した名前。
何をやっているかというと、
RGB を 111 の 2進数と見立てて 0~7 の 10進数 に換算してる。
これで、各頂点に番号を振ったのも同然。
あとは、個々でパラメータを反映してやるだけ。
blender のVertexPaint は デフォルトだとアルファが使えないので、今回のやり方だとRGBの3つしか使えないけど、アドオンでアルファを使えるようにしたら、ARGBの 4つが使えるので、最大15個の頂点を制御できると思う。試してないけど。
あとは、この 1 ~ 6 の値を if ノードで判定しながら頂点を動かします。
LocalPositionノードは、メッシュが持つ頂点の位置で、メッシュの中央からの座標になります。
上の図の場合、VertexColor が RGB(0,1,1) のとき(= 3) という値が来たときだけ、 ScalarParameter(上図のRightUpper)を流して、それ以外は 0 を流します。
マテリアルが受け取る値は 0 ~ 1
0 のときMAXなんで、 気持ち悪ければ OneMinus ノード使ってもいいのですが、計算が増えるので処理負荷を考えてここは受け入れています。
各頂点は、Meshの原点から離れた位置にいます。ここに掛け算することで、方向を保ったまま、原点に近づいたり離れたりするわけです。
で、この掛け算した結果を、元の頂点位置から引き算することで結果的に凹みます。
用意したMesh が最大値の状態なので、こういった発想に至りました。
あとは連鎖的に、次々各頂点の計算をして引いていきます。
もう少し違うやり方もありそうな気がします。
中央以外の頂点を計算し終えたら仕上げ。
TransformPosition に渡して、そこから AbsoluteWorldPosition を 引いてようやく 出力できます。すでに存在するメッシュに対して、部分的に頂点を動かしたら、この計算しておくことで、相対的な動きになります。
Lerp ノードのところは、頂点カラーを確認するためのものなので、以下の形で問題ないです。
マテリアルは完成です。
新しく Actorブループリントを用意して、StaticMesh を AddComponent します。
そこに インポートしたメッシュと出来立てのマテリアルをセット。
メッシュのマテリアルをいじるには、Dynamic Material Instanceを用意します。
Targetにつながった StaticMesh は、 Viewportで追加したやつ。左のリストからドラッグ&ドロップ。
Source Material のところに 今回用意したマテリアルをセット。あとはReturnValue ピンから 変数に昇格(Promote to Variable)させておきます。
パラメータを管理するための配列を用意します。
配列の中身を個別に取り出す関数
Pure型にするのをオススメ
そして、この配列の中身を一気にマテリアルに反映するのがカスタムイベント。
下のほう見切れてるけど、同じような形なので省略。
マテリアルパラメータ名と、配列変数の Index が合ってさえいれば問題なし。
ひとまずこれで必要なものは全て揃いました。
あとは配列の中身を書き換えて、カスタムイベントを呼ぶ。
これだけです。
Twitterにあげた動画は、ランダムにパラメータ書き換えて遷移するように特別に組みました。
エンジンの操作(オペレーション)についてはかなり省いているので、わかりにくかったらごめんなさい。謎なところなどあればコメントいただけると補間します。
正7角形までだけど、 頂点の数が変わっても簡単に対応できます。
使用できるカラーは以下の8色。
RGBの各輝度は 1.0 = 255 です。実は blender のRGBの扱い方が 0~1.0 なのです。
将来的に、HDR時代が当たり前になったら、255 とか FF みたいなこと言うと年寄り扱いされるかもしれないので今から慣れておくといいかも。
円錐の角数を変えてたので試してみた。マテリアルは使いまわし。
ブループリント複製して、StaticMeshの中身差し替えて、減った頂点のぶん不要な処理を削っただけです。
ひとまずここまで作れて満足してます。
UE4は普通にメッシュ描けるので、ぶっちゃけこの方法は必要ないと思います。
頂点カラーで特定の頂点を動かすことができるのに気づけたのはよかった。
Widgetでシェイプが扱えるようになるといいな。
ではでは
すてきなレーダーチャートライフを!