読者です 読者をやめる 読者になる 読者になる

みつまめ杏仁

アンリアルエンジン(UE4)でGUIを作るためにゴニョゴニョしてます。UIデザイナーの皆様の助けになれば幸いです。

わりと本気のコンボカウンター 《Widgetブループリント編》

続きです。

 前回の記事はこちら。

 

わりと本気のコンボカウンター 《準備編》 - みつまめ杏仁

わりと本気のコンボカウンター 《UMG編》 - みつまめ杏仁

 

 

Widgetブループリント

絵的な素材が用意できたところで、いよいよブループリントに手をつけていきます。

まずブーリアン型の変数を一つ用意。これは、「HITs」と下敷きのアニメーションを初回と2回目以降とで分けるためのものです。これを 初めから置いてある、EventConstruct ノードにSetでつないで、初期値を false にしておきます。(①)

f:id:hiyokosabrey:20161008220412p:plain

最後に準備用の関数をつないでいます。(③)

Add to Viewport されるたびに、この関数が実行されるのは無駄なので、DoOnceノードを間に入れておきます。(②)

このセットアップ関数の中身は以下。

f:id:hiyokosabrey:20161008221211p:plain

キャンバスに置いたImageパーツはマテリアルにパラメータノードを仕込んでいるので、パラメータに値を渡していじることで、カラーやUVを変えることができます。そのためには、Get Dynamic Material ノードが必須です。このノードにはReturnValue という出力ピンがあるので、その内容を配列に積んでおきます。

扱い方が少し違うので、「HITs」だけは配列にはしません。

このGet Dynamic Material の操作は、マテリアルを操作する直前で行ってもいいのですが、私はReturnValue(戻り値)を変数化しておくこの方法をよく使います。

メモリは必要になりますが、なんとなく処理コストが安くなる気がします。

 

次に 新たに変数を3つ追加します。

f:id:hiyokosabrey:20161008223322p:plain

 

カウンターを表示する関数を作っていきます。

この関数はInteger型の値をひとつもらって、それを桁に分解して表示するという内容です。いつ呼ばれるかは、プレイヤー次第なのでわかりません。コンボ受付中はカウントアップするので問題ないのですが、受付が終了してフェードアウトの最中に呼ばれると問題です。かといってフェードが終わるのを待たせるのは、ユーザビリティ的に問題アリです。

そこで、フェードアウト中に呼ばれたら、フェードアウトのアニメーションを止める処理を入れます。

f:id:hiyokosabrey:20161008224348p:plain

別の場所でフェードアウト用のタイマーをセットしていて、そのタイマーをコントロールするためにTimerHandle型の変数を利用しています。

今は↓この部分です。

f:id:hiyokosabrey:20161008225159p:plain

 

次に受け取った数字を桁に毎に分解する関数を作ります。

一、十、百、それぞれの桁の有り無しを判定して、あれば0~9の数字を取り出し、なければ  -1 にします。

先に作っておいた配列変数 DigitNumArray に 桁毎の結果を入れていきます。

f:id:hiyokosabrey:20161009105209p:plain

桁を分解する方法は、割り算(÷)と剰余(%)のノードを使います。

 

f:id:hiyokosabrey:20161009110955p:plain

 Int型同士の割り算は、小数点以下は切り捨てになります。

 

 配列の中身(要素)を変更するのは Set Array Elem ノードを使います。

この Set Array Elem ノードですが、あらかじめ要素が存在しているのが前提です。

あらかじめ配列の要素を用意する方法はいくつかあります。今回はノードを使わずにセトしました。配列を作ったときの初期値です。一度コンパイルすると追加できます。

f:id:hiyokosabrey:20161009112958p:plain

ちなみに、Addノードは新しく要素を追加するときに使うもので、何度も呼び出される関数の中に置くと要素が増えることになるのと、追加する順番に注意を払う必要があります。

 

続きに、できた関数をつないで、さらにカウント数に応じてカラーを変える仕組みをつなぎます。

f:id:hiyokosabrey:20161009113748p:plain

関数内では、ローカル変数という使い捨ての変数を使うことができます。

カラーを計算して利用した後は覚えておく必要はないので(この関数の外では役に立たない)ローカル変数を新しく作っています。

今回のカウントは 999まで表示可能ですが、カラーは100以上で変化しないようになっています。精度と調整のしやすさを考えて0~200でクランプします。その値を InverseLerpノードで割合に変換します。

f:id:hiyokosabrey:20161009185924p:plain

例えば 100 だと InverseLerpノードは  0.5 を返してきます。↑の図で、ちょうど赤から紫に変化するあたりです。InverseLerpノードは 指定した範囲のどの辺にいるかを割合で返してくれる便利なノードで、マテリアルのパラメータとして相性ばっちりです。

上の例では、コンボ数が 20、40、60、80、100 を越えるごとに色が変わります。

紫色の次がいい色にならなかったので、100で変化が止まっています。

この辺は自由に加減してみてください。

 

というわけで今↓ココです。

f:id:hiyokosabrey:20161009190634p:plain

次に進みます。

各桁の表示部分です。すでに数字を桁毎に分解してあるので、配列からGetノードで取り出しつつ、アニメーションの再生をマクロを使って処理しています。

f:id:hiyokosabrey:20161009191235p:plain

マクロは同じことを何度もする場合にラクちんなので積極的に利用します。

上記のマクロは3つとも同じ内容ですが引数を変えています。

マクロの中身はこうなっています。

f:id:hiyokosabrey:20161009192113p:plain

さらにマクロがあります。

受け取った数字から テクスチャのUVを求めて、0未満(-1)だったら 0.0 を、0以上だったら 1.0 をパラメータにしてマテリアルにセットするマクロです。

f:id:hiyokosabrey:20161009192445p:plain

 Set Vector Parameter Value ノードはベクター型のパラメータで、LinearColorの形で値を渡します。セットアップ関数で作っておいた Material Instance Dynamic型の配列からGetノードで取り出してつなぎます。

 

これで数字部分の表示は完成です。

f:id:hiyokosabrey:20161009193809p:plain

 

次に HITs の表示です。f:id:hiyokosabrey:20161009194717p:plain

色の変更と、アニメーションの分岐、フラグのセットをしています。

 

この後、タイマーのセットをするのですが、その前に用意するものがあるので、いったんこの関数の編集を止めます。

 

Event Dispatcher(イベントディスパッチャー)を2つ用意します。

f:id:hiyokosabrey:20161009210637p:plain

コンボカウントの受付終了と、退場演出のフェードアウトが終わったことを通知します。通知する相手はこのWidgetを CreateWidgetしたブループリントになります。

 

次に 退場演出のイベントを用意します。

カウントアップの関数から EventGraph に戻ります。

f:id:hiyokosabrey:20161009211806p:plain

赤いのはカスタムイベントです。作ったEvent Dispatcherを2つとも投入です。

Event Dispatcherはグラフにドラッグ&ドロップして取り出します。その際選択肢が出てくるので、Call を選択します。

f:id:hiyokosabrey:20161009212247p:plain

ようやくTimerHandle型の中身が判明しました。フェードアウトのアニメーションが終了したことを通知するタイマーだったのです。

目覚ましが鳴る前に起きてしまって、うっかりタイマーを止めずに顔を洗っていると鳴り出してイラッ・・・みたいな状況を避けるためのものです。

 

ここで、先ほど編集を中断したカウントアップの関数に戻ります。

いよいよラストです。

f:id:hiyokosabrey:20161009213033p:plain

f:id:hiyokosabrey:20161009213619p:plain

CreateEvent ノードは、作成済みの関数やイベントを選ぶカタチになるので、いったん中断したというわけです。

 

おつかれさまです。これでWidget完成です。

次回は、このWidgetを呼び出すところを仕上げて終了です。