みつまめ杏仁

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

UMG でトランジションを作ってみる

f:id:hiyokosabrey:20160221205241j:plain

f:id:hiyokosabrey:20160221205247j:plain

丸い穴が小さくなっていき最後は真っ黒になる、おなじみ?の画面切り替えです。

昔のアニメでよく見かけた気がします。最近のゲームではどうぶつの森で使われてます。

トランジションのアイリスエフェクトとかいうそうですが動画は詳しくないのと編集ツールにごとに呼称が若干違っているようなので間違ってたらごめんなさい。

で、これをUMGを使って再現してみました。UMGは描画の順番が最後っぽいので向いていると思います。フェードインアウトと同じように使えます。

 

UE4はスターターコンテンツが無いプロジェクトは背景が何もなくて真っ暗なので、サンプルでは歌川広重の絵を利用しました。

まずマテリアルを用意します。今回テクスチャは使用しません。

f:id:hiyokosabrey:20160221205920p:plain

 右端の基本マテリアルは、UMGで使うのでUserInterface用にします。

肝は Radial Gradient Exponential というでっかいノード。

f:id:hiyokosabrey:20160221210314p:plain

 このノードは下図のような円形のグラデーションを出力してくれます。

f:id:hiyokosabrey:20160221210537p:plain

一般的なTVのアスペクト比で表示すると、こうなってしまいます。

f:id:hiyokosabrey:20160221211009p:plain

これを補正するために、Texture Coordinate ノードで調整します。

今回UMGのイメージパーツ(スタティックメッシュのように頂点ごとにUV値を割り当てたりできない)を使うので、UVはタテヨコの比率に関係なく、0.0~1.0で割り当てられます。

f:id:hiyokosabrey:20160221212144p:plain

横方向を1とした場合、16:9なので、9÷16 でタテ方向のV Tiling値を 0.5625にすると正円になります。

f:id:hiyokosabrey:20160221212510p:plain

↑はTextureCoordinateの中の状態。このTilingの値は、ノードの外で掛け算しても同じ結果になるので、今回は 1.0 のまま(初期値)で使用します。

f:id:hiyokosabrey:20160221212253p:plain

V値にだけ掛けたいので、いったんBreakOutFloat2Components ノードでUV に分解。

f:id:hiyokosabrey:20160221213755p:plain

最後にMakeFloat2 ノードでもとのVector型に戻しています。AppendVectorノードでもOK。

円の中心位置と円の大きさが変化するので、それぞれパラメータとして接続します。

 Radius ・・・ 円のサイズ(Scalar型)

 Position ・・・ 円の中心位置(Vector型)

円の中心位置についてもアスペクト比対応しないとタテ方向の位置がズレます。VTilingの補正と同じ値を掛けてやります。 こういった変動しない固定の値を使うような『補正』はマテリアル内で済ませておく方が、ポジションの指定がシンプルになります。

例えば○の中心を画面のど真ん中にしたい場合は  ヨコ方向 0.5、タテ方向 0.5 です。

最後に Radial Gradient Exponential ノードにある入力PINについて書いておきます。 Density はグラデーションの滑らかさで、最小値1.0から数値が大きくなればなるほど境界線がハッキリしてきます。いろいろ加減してみると効果が分かります。今回は 20 にしてみました。これでマテリアルは完成です。保存しておきます。

 

次に表示用のWidgetを用意します。

画面いっぱいにImageパーツを拡げます。Iris という名前を付けました。

DetailsタブのAppearance > Brush の Imageのところに作ったマテリアルをセットします。実験なら、ここでもう一枚適当な絵を下敷きとして配置しておくといいです。

 

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

割り当てたマテリアルのパラメータを触りたいので、EventConstruct

Get Dynamic Material ノードをつないで、ReturnValue(返り値)を変数化しておきます。

f:id:hiyokosabrey:20160221225554p:plain

これはWidget専用のノードで、他のブループリントだと Create Dynamic Material Instance ノードになります。

ここで、円の大きさをアニメーションさせるためのFloat型の変数を一つ用意しておきます。

RadiusValue という名前にしました。初期値は 0.0 をセットしておきます。

 

次に、スタートさせる関数を作ります。

f:id:hiyokosabrey:20160221231030p:plain

RadiusValue に開始のための値 1.0 をセットしています。あとは、EventConstructionで変数化しておいた、 DynamicMaterialInstance経由でパラメータをセットします。

関数のInputs(引数)に Vector2D 型をひとつ。そこから円の中心位置を受け取ってパラメータとして渡せるようにします。

 

最後にアニメーションの部分を作ります。

EventGraphに戻って、Event Tick につないでいきます。

f:id:hiyokosabrey:20160221231904p:plain

Event Tick は、 表示開始してから、WidgetがRemoveされるまで常に実行され続けます。なので画面が真っ暗になったら処理を止めないと無駄な処理が走ってしまいます。

アニメーション用に用意した変数 RadiusValue は初期値が 0.0なので、スタートさせる関数が呼ばれない限り Branch ノードで先に進まないようにしておきます。

RadiusValueの値を 1.0 から徐々に 0.0 に減らしてゆくために 0.9を掛けています。この方法だと限りなく0.0 に近づくのですが、見た目には変化が分からない状態になるので、ある程度まで小さい数字になったら、強制的に 0.0 にしています。こういった分岐で後に続く値を変化させたい場合は、Selectノードが便利です。

プログラム界では三項演算子というやつだそうです。マテリアルのノード Lerp(Linea Interpolate) と同じような使い方ができます。例えで比較するとLerpノードはお風呂の蛇口(水とお湯を混ぜる混合栓タイプ)で、Selectノードは鉄道のポイントという違いがありますが、Branchのように後に続くルートが分岐しないという点では、同じと言っていいのではと思います。

Widgetはこれで編集完了です。

 

ようやく表示部分。

レベルブループリントを編集します。

f:id:hiyokosabrey:20160222000109p:plain

Create Widget ノードで作ったWidgetをCreateしてAdd to Viewportノードで画面に表示します。

Input イベントノードで 今回は スペースバー を選択しました。

アイリスエフェクトをスタートさせる関数を呼び出せばOKです。

ひとまず完成。