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

みつまめ杏仁

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

UMGでキラキラ効果

UE4 UI UMG Widget

f:id:hiyokosabrey:20160213232310p:plain

UMGでキラキラ効果を作ってみます。

UMGの動画キャプチャがうまくいかず、静止画しか載せられませんがかなりキラキラします。用途が伝わりにくいかと思い頑張って金塊の絵を描きました。

リワード演出とか、ランクアップ演出とかで使えるのではないかと。

 

キラキラする数と範囲を調整できる仕様です。

ではさっそくテクスチャから。

f:id:hiyokosabrey:20160213233028p:plainキラキラ本体と、f:id:hiyokosabrey:20160213233037p:plain グロー用の2枚。

サイズは 128x128、加算で使うのでアルファは無しです。私はよくTarga形式を使います。この場合24bitにしました。

このテクスチャを使ったマテリアルをそれぞれ用意します。

キラキラ本体のマテリアルはこんなカンジ。

f:id:hiyokosabrey:20160213233717p:plain

4.10からベースマテリアルのタイプに「User Interface」が追加されています。

f:id:hiyokosabrey:20160213234010p:plain

ライトの計算やカリングの判定が不要なのでコンパクトです。UMGで使う場合は強制的にこのタイプになります。

Lerpノードを使うと、モノクロのテクスチャに対して、Photoshopのグラデーションマップのようなことができます。

 

グロー用のマテリアルは以下。

f:id:hiyokosabrey:20160213234416p:plain

加算半透明(Addtive)でたくさん重なるので、色は暗めです。テクスチャの状態で調整するのではなく、マテリアルで調整します。

f:id:hiyokosabrey:20160213234725p:plain

マテリアルが準備できたら、キラキラ用子Widgetを作ります。

まず編集モード「Designer」から。

キャンバスにImageパーツを2つ配置します。サイズはグロー用が大きく 256x256 に引き伸ばします。キラキラ本体は、そのままの 128x128です。

エディタ右 Detailsタブの Appearance > Brush > Image のところに、用意しておいたマテリアルをセットします。

f:id:hiyokosabrey:20160213235532p:plain

配置できたら、アニメーションを追加します。トラックはこんなカンジ。

とりあえずパーツには "Shine" と "Glow" という名前を付けました。

f:id:hiyokosabrey:20160214000457p:plain

f:id:hiyokosabrey:20160214001110p:plain

0.45 Secで完全に消えます。加算半透明なのでOpacityではなく、RGBの輝度を落とせば消えてくれます。ただ暗くするだけだと華やかさが出ないので、途中彩度の高い黄色や茶色を経由させています。

アニメーションができたら、グラフ編集に行く前にやっておくことがあります。

初期状態を非表示にしておきます。VisibleではなくColor And Opacityの設定を真っ黒にしておきます。

f:id:hiyokosabrey:20160214002323p:plain

アニメーションの最終フレームと同じ状態にしておくことで開始時に一斉に同時表示されるのを回避します。

 

ここで編集モードを「Graph」に切り替えます。

 変数を一つ用意します。Box2D型です。

f:id:hiyokosabrey:20160214040511p:plain

この変数タイプは、Vector2Dを2つ持つ形です。

f:id:hiyokosabrey:20160214041233p:plain

今回この変数を使ってキラキラの発生エリアを限定します。

で、親Widgetから受け取れるようにする関数が以下。右端が用意した変数。

f:id:hiyokosabrey:20160214041753p:plain

引数(Inputs)はもちろんBox2D型ですがいきなり、Breakノードで分解してます。

これはBox2D型のままだと引き算ができないからです。なぜ引き算するかというとキラキラの大きさを元に表示開始位置を補正するためで、パーツの原点が左上にあるために補正しないと全体的に右下にずれた見た目になります。

f:id:hiyokosabrey:20160214043021p:plain

そこでキラキラのサイズの半分を引いてやると、左上にずらすことができます。

f:id:hiyokosabrey:20160214044107p:plain

直接 256x256の半分の128x128を計算に使ってもいいのだけれど、あとからデザインやサイズを変更した場合に対応するのが面倒なので、ここは自動的に割り出すようにします。今回の例はグロー効果の方がサイズが大きいので、その大きい方のサイズを取得して2で割って使ってます。大きい方をキャンバスの左上に置いているからです。

f:id:hiyokosabrey:20160214044604p:plain

こういった「仕込み」は、デザイナーにとっては面倒だし小難しい向きもあると思いますが、地味に調整箇所が減るので後から触るときにラクです。

 

次にアニメーションを再生する関数です。

f:id:hiyokosabrey:20160214102651p:plain

とりあえず関数名は "start" にしました。(この名前は後で使います)

Wow はアニメーションの名前です(思いつかなくて・・・)。

ポイントは、下の Get End Time ノードです。これでアニメーションの尺(長さ)を取得して、次の Set Timer by Function Name ノードにつないでいるとこです。

Play Animation ノードは、再生を開始しますが、開始の命令を発したらすぐに次のノードに進んでしまいます。この関数は再生が終わって次の表示場所を決めたら再び呼び出されるという扱いにするので、再生が終わってないのに呼び出されるとマズイので、Timer ノードをつないで一定時間後に呼び出すようにしています。

FunctionName はこのあと作る関数名 "PositionSet" の名前を入力しています。

 

 で、そのPositionSet関数がこれ。(SetPositionというノードがあるので逆にしただけ・・・)

f:id:hiyokosabrey:20160214103613p:plain

表示範囲を変数"Area"が持っているので、それを Break Box2D して、さらにスプリットするとFloat型のPINに分解できます。

f:id:hiyokosabrey:20160214104048p:plain

分解したFloat型の値を、 Random Float in Range ノードにつなぐことで指定した範囲内でランダムな値を取り出せます。

ここで決定したランダムな位置を、Set Render Transform ノードで反映させます。

なぜRenderTransformかというと、今回移動させるキャンバスパネルの設定が下図のようになっているからです。

f:id:hiyokosabrey:20160214105154p:plain

キラキラの位置が決まったところで、最後にアニメーション開始までの時間差をランダムに設定します。先の関数と同じ Set Timer by Function Name ノードにアニメーション開始用の関数名を書いて、Timeピンには Float型のランダム発生ノードをつないでいます。

f:id:hiyokosabrey:20160214105504p:plain

以上で子Widgetは完成です。

 

Widgetときたら、次に親Widgetです。

まずはキャンバスにキラキラの範囲指定用のCanvasPanelを置きます。

f:id:hiyokosabrey:20160214110455p:plain

後ろの絵は無くても構いません。(頑張って描いたので貼っておこう)

実際に表示しないので、BehaviorのVisiblity設定は Hiddenにしておきます。

f:id:hiyokosabrey:20160214110845p:plain

名前は"shineArea" にしました。is Variable のチェックは忘れずに。

 

編集モードを 「Graph」に切り替えます。

まず、キラキラの表示数を持たせる変数を整数型でひとつ用意します。

初期値は 20くらいでしょうか。

 

EventConstructionにつないでいきます。

f:id:hiyokosabrey:20160214111728p:plain

ForLoopノードでキラキラの数分ループを回します。

Create Widget ノードで 子Widgetを生成しつつ、Viewportではなく、親のキャンバスパネルに子供として追加してます。

f:id:hiyokosabrey:20160214112130p:plain

AutoSizeノードは、付けておかないと固定サイズで表示されてしまいます。ZOrderは表示優先なので、とりあえずForLoopから出てきたIndex値をつないで同じ優先にならないようにしています。何かと重なっておかしな見た目になるようだったら、このIndex値に数値を足して下駄をはかせるとよいかと。

 

最後、子Widgetの関数を呼び出し(CallFunction)しています。

表示範囲の中でランダムなポジションを決めるので、先に表示範囲をセットしてやらないといけません。なので、 AreaSet関数を先につなぎます。これは引数にBox2Dが必要なので、それを渡すためのマクロをつないでいます。

マクロは最初下のような状態でした。

f:id:hiyokosabrey:20160214113104p:plain

表示範囲設定用のキャンバスパネル "shineArea" からサイズとポジションを取得してBox2D型に整形しています。

Widgetの編集は以上で完了です。

 

いよいよ表示です。

レベルブループリントに親Widgetの表示をつなぎます。

f:id:hiyokosabrey:20160214113647p:plain

いかがでしょうか?

f:id:hiyokosabrey:20160214114015p:plain