続きです。
前回の記事はこちら。
わりと本気のコンボカウンター 《UMG編》 - みつまめ杏仁
Widgetブループリント
絵的な素材が用意できたところで、いよいよブループリントに手をつけていきます。
まずブーリアン型の変数を一つ用意。これは、「HITs」と下敷きのアニメーションを初回と2回目以降とで分けるためのものです。これを 初めから置いてある、EventConstruct ノードにSetでつないで、初期値を false にしておきます。(①)
最後に準備用の関数をつないでいます。(③)
Add to Viewport されるたびに、この関数が実行されるのは無駄なので、DoOnceノードを間に入れておきます。(②)
このセットアップ関数の中身は以下。
キャンバスに置いたImageパーツはマテリアルにパラメータノードを仕込んでいるので、パラメータに値を渡していじることで、カラーやUVを変えることができます。そのためには、Get Dynamic Material ノードが必須です。このノードにはReturnValue という出力ピンがあるので、その内容を配列に積んでおきます。
扱い方が少し違うので、「HITs」だけは配列にはしません。
このGet Dynamic Material の操作は、マテリアルを操作する直前で行ってもいいのですが、私はReturnValue(戻り値)を変数化しておくこの方法をよく使います。
メモリは必要になりますが、なんとなく処理コストが安くなる気がします。
次に 新たに変数を3つ追加します。
カウンターを表示する関数を作っていきます。
この関数はInteger型の値をひとつもらって、それを桁に分解して表示するという内容です。いつ呼ばれるかは、プレイヤー次第なのでわかりません。コンボ受付中はカウントアップするので問題ないのですが、受付が終了してフェードアウトの最中に呼ばれると問題です。かといってフェードが終わるのを待たせるのは、ユーザビリティ的に問題アリです。
そこで、フェードアウト中に呼ばれたら、フェードアウトのアニメーションを止める処理を入れます。
別の場所でフェードアウト用のタイマーをセットしていて、そのタイマーをコントロールするためにTimerHandle型の変数を利用しています。
今は↓この部分です。
次に受け取った数字を桁に毎に分解する関数を作ります。
一、十、百、それぞれの桁の有り無しを判定して、あれば0~9の数字を取り出し、なければ -1 にします。
先に作っておいた配列変数 DigitNumArray に 桁毎の結果を入れていきます。
桁を分解する方法は、割り算(÷)と剰余(%)のノードを使います。
Int型同士の割り算は、小数点以下は切り捨てになります。
配列の中身(要素)を変更するのは Set Array Elem ノードを使います。
この Set Array Elem ノードですが、あらかじめ要素が存在しているのが前提です。
あらかじめ配列の要素を用意する方法はいくつかあります。今回はノードを使わずにセトしました。配列を作ったときの初期値です。一度コンパイルすると追加できます。
ちなみに、Addノードは新しく要素を追加するときに使うもので、何度も呼び出される関数の中に置くと要素が増えることになるのと、追加する順番に注意を払う必要があります。
続きに、できた関数をつないで、さらにカウント数に応じてカラーを変える仕組みをつなぎます。
関数内では、ローカル変数という使い捨ての変数を使うことができます。
カラーを計算して利用した後は覚えておく必要はないので(この関数の外では役に立たない)ローカル変数を新しく作っています。
今回のカウントは 999まで表示可能ですが、カラーは100以上で変化しないようになっています。精度と調整のしやすさを考えて0~200でクランプします。その値を InverseLerpノードで割合に変換します。
例えば 100 だと InverseLerpノードは 0.5 を返してきます。↑の図で、ちょうど赤から紫に変化するあたりです。InverseLerpノードは 指定した範囲のどの辺にいるかを割合で返してくれる便利なノードで、マテリアルのパラメータとして相性ばっちりです。
上の例では、コンボ数が 20、40、60、80、100 を越えるごとに色が変わります。
紫色の次がいい色にならなかったので、100で変化が止まっています。
この辺は自由に加減してみてください。
というわけで今↓ココです。
次に進みます。
各桁の表示部分です。すでに数字を桁毎に分解してあるので、配列からGetノードで取り出しつつ、アニメーションの再生をマクロを使って処理しています。
マクロは同じことを何度もする場合にラクちんなので積極的に利用します。
上記のマクロは3つとも同じ内容ですが引数を変えています。
マクロの中身はこうなっています。
さらにマクロがあります。
受け取った数字から テクスチャのUVを求めて、0未満(-1)だったら 0.0 を、0以上だったら 1.0 をパラメータにしてマテリアルにセットするマクロです。
Set Vector Parameter Value ノードはベクター型のパラメータで、LinearColorの形で値を渡します。セットアップ関数で作っておいた Material Instance Dynamic型の配列からGetノードで取り出してつなぎます。
これで数字部分の表示は完成です。
次に HITs の表示です。
色の変更と、アニメーションの分岐、フラグのセットをしています。
この後、タイマーのセットをするのですが、その前に用意するものがあるので、いったんこの関数の編集を止めます。
Event Dispatcher(イベントディスパッチャー)を2つ用意します。
コンボカウントの受付終了と、退場演出のフェードアウトが終わったことを通知します。通知する相手はこのWidgetを CreateWidgetしたブループリントになります。
次に 退場演出のイベントを用意します。
カウントアップの関数から EventGraph に戻ります。
赤いのはカスタムイベントです。作ったEvent Dispatcherを2つとも投入です。
Event Dispatcherはグラフにドラッグ&ドロップして取り出します。その際選択肢が出てくるので、Call を選択します。
ようやくTimerHandle型の中身が判明しました。フェードアウトのアニメーションが終了したことを通知するタイマーだったのです。
目覚ましが鳴る前に起きてしまって、うっかりタイマーを止めずに顔を洗っていると鳴り出してイラッ・・・みたいな状況を避けるためのものです。
ここで、先ほど編集を中断したカウントアップの関数に戻ります。
いよいよラストです。
CreateEvent ノードは、作成済みの関数やイベントを選ぶカタチになるので、いったん中断したというわけです。
おつかれさまです。これでWidget完成です。
次回は、このWidgetを呼び出すところを仕上げて終了です。