UMGで必殺技とかのカットイン演出を作ってみる

##はじめに
アドベントカレンダー初参加です。よろしくお願いします。
![ScreenShot00002.jpg](https://qiita-image-store.s3.amazonaws.com/0/212880/90dd7fe1-c939-0c77-8380-55229d3ec540.jpeg)
サンプルの動画 → https://youtu.be/95WP5W0WhQI

UMGで大きいキャラ絵出したいな～と考えたのがきっかけでした。
試しに作ってみたカットイン演出について作り方などを書いてみようと思います。
Photoshopでのテクスチャ作業手順ついてはなるべくショートカットキーや謎のボタンを使わないように心がけてみました。

##マスクテクスチャをつくる
入ってくる時と消える時で開いたり閉じたりする**マスクテクスチャ**を用意します。
以下Photoshopで作業する場合の例です。

まず画面サイズの真っ黒いドキュメントを作ります。
![fig00.png](https://qiita-image-store.s3.amazonaws.com/0/212880/bcb820e0-7f4f-3c04-2e50-10ac7e5415e0.png)
そこに
レイヤー ＞ 新規塗りつぶしレイヤー ＞ グラデーション  を選択。
![fig01.png](https://qiita-image-store.s3.amazonaws.com/0/212880/6f4cc126-7154-c32f-e9ba-957d4d9dfabb.png)

グラデーションの設定はこんな感じ。
![fig02.png](https://qiita-image-store.s3.amazonaws.com/0/212880/56850d72-4013-5331-346a-cd0a31d8e3f8.png)
0,0,0 の真っ黒と 255,255,255 の真っ白 のグラデーションです。
ドキュメントいっぱいにグラデーションレイヤーが作られます。

![fig04.png](https://qiita-image-store.s3.amazonaws.com/0/212880/534bf033-54d7-af02-9091-50ac6ba3921d.png)


できたグラデーションレイヤーを選択した状態で、続けて、再びメニューから
レイヤー ＞ スマートオブジェクト ＞ スマートオブジェクトに変換  を選択。

![fig03.png](https://qiita-image-store.s3.amazonaws.com/0/212880/fdaea8ca-ffd8-eff1-dec2-8007199b01b9.png)
レイヤーのサムネイルにスマートオブジェクトのアイコンが付けばOK。

仕上げにこのレイヤーを変形します。
Ctrl + Ｔ で変形モードにします。この時四隅にある小さな四角いハンドルポイントを、**Ctrlキー を押しながらドラッグ**します。
Ctrlキーを押しながらだと、４か所の頂点をバラバラに移動させることが可能になります。また、
一旦 Ctrlキーで移動し始めたら、そのままShiftキーも追加で押すと、最初のポイントから45°刻みの方向に移動できます。
上下にスキマが開いたりしないように注意しつつ、いい感じのカットになるように変形させます。
![fig05.png](https://qiita-image-store.s3.amazonaws.com/0/212880/e0c64a88-77ca-38ce-f871-62a04e14c050.png)
変形が満足できたら、 ○ボタンをクリックするか、テンキーの方の Enterキーで確定させます。

これをTarga形式、24bit で書き出します。

##背景用のテクスチャ
マスクテクスチャと同じ方法で、今度は背景用のグラデーションテクスチャを作ります。
サイズは小さくて構わないです、4x128 くらいでしょうか。
↓実寸
![fig06.png](https://qiita-image-store.s3.amazonaws.com/0/212880/5d852d1a-887d-3b3e-5cae-b417c86aba09.png)


##キャラ絵とか
キャラ絵は頑張ってGrayちゃん描きました。
![fig07.png](https://qiita-image-store.s3.amazonaws.com/0/212880/90b34f4b-6268-6117-8ec8-f2c8055a05d6.png)

エフェクトのテクスチャはこんなんです。加算半透明なので暗くしてあります。
↓実寸
![fig08.png](https://qiita-image-store.s3.amazonaws.com/0/212880/2d41ab81-cd8a-4b3f-cc24-4571e7054311.png)


##テクスチャインポートする
マスクテクスチャと背景用のグラデテクスチャは、Grayscale の No sRGB で **リニアグレイスケール**にします。
Maskテクスチャだと、DTX圧縮が掛かってドットが荒れるのと、sRGB をOFFにするのはテクスチャの階調をそのまま使いたいからです。

あとは普通のインポート設定で問題ないです。せっかくのキャラ絵なので、非圧縮のUserInterface2Dにしますが、そこはメモリと相談で。


##カットイン用のマテリアル
今回の肝になるのがマテリアルです。全景はこんな感じ。
![fig11.png](https://qiita-image-store.s3.amazonaws.com/0/212880/c0e5031a-35fa-c4f2-accb-3bbde33e7525.png)


まずマスク部分。**ScreenPosition** と マスクテクスチャとつないで、**SmoothStep** でカットインのアニメーションを実現します。
![fig09.png](https://qiita-image-store.s3.amazonaws.com/0/212880/a25f3982-96e7-f18e-b022-da9f7b26a1fe.png)
WidgetBlueprint から、Value という名の ScalarParameter 経由で開き具合を調節します。


つづいて背景。
![fig10.png](https://qiita-image-store.s3.amazonaws.com/0/212880/95b477bc-0336-110c-d57c-fe15d50ba23b.png)
イイ感じの流線効果になるようNoise、Pannar、TexCoordinate の設定を調整します。
参考程度に今回の設定値を書いておきます。

| 設定名 | 設定値 | ノード |
|:-:|:-:|:-:|
| UTiling   |1.0   |TexCoord   |
| VTiling   |50.0   |TexCoord   |
|Speed X   |-10.0   |Panner   |
|Speed Y   |0.0   |Panner   |
|Scale     |0.4   |Noise   |

キャラも背景もマスクの部分は共通なので、このマテリアルを親マテリアルにして、インスタンスを作って使います。キャラと背景の切り分けは、Switch Parameter ノードを使っています。

![fig12.png](https://qiita-image-store.s3.amazonaws.com/0/212880/870f9fd3-e5b2-b6a3-9301-358eb261889c.png)


あと、エフェクトは加算半透明で、マテリアルの Blend Mode が **Additive** になり、別にしないといけないのでもう一つ似たようなのを作ります。
![fig13.png](https://qiita-image-store.s3.amazonaws.com/0/212880/21f13135-de77-bc9a-e7f4-64ed988a8483.png)


##WidgetBlueprint
UMGでImageに作ったマテリアルインスタンスをセットしたら、レイアウトしてアニメーションを作ります。
![fig14.png](https://qiita-image-store.s3.amazonaws.com/0/212880/be8e3da2-116d-b483-ab07-6fe363184f70.png)

親マテリアルの Scalar Param のDefault値を 0.002 にすると、カットインの形が少しは分かるのでアニメーションの加減がやりやすいと思います。作業が終わったら 1.0に戻しておきます。

###開閉用のパーツ
このアニメーションに合わせて、カットインの開閉をコントロールするパーツ（Imageあたりが良いかと思います）をキャンバスに一つ追加します。
画面には描かないので、Visibility を **Collapse** にしておきます。
この見えない隠しパーツの Pivot（他に、無難でBlueprintから触れるのであればなんでも）の値をアニメーションさせます。値は **1.0** ～ **0.002** の間で変化させます。
参考までに今回作ったカーブを貼っておきます。
![fig15.png](https://qiita-image-store.s3.amazonaws.com/0/212880/03e3168b-4613-4707-783f-3170fa94ff2c.png)

マテリアルの中で、マスクの境界をジャギらないようにSmoothStep を使っています。そのノードで指定する Max の値から 0.001 引いた値を Min の値にしているので、引き算しても０ゼロにならない値として 0.002 を使っています。

このPivotの値をリアルタイムに拾って、カットインのキャラと背景のマテリアルパラメーターに渡してやることで、カットインの閉じたり開いたりという動きができます。
![fig23.png](https://qiita-image-store.s3.amazonaws.com/0/212880/ee951e9b-6c87-1b98-c841-511f68a86741.png)

その 『パラメータの横流し』 は Event Tickでやります。
![fig16.png](https://qiita-image-store.s3.amazonaws.com/0/212880/afec827f-7bad-df5c-28fd-7876f7177091.png)
上図の ImageNull っていうのが、キャンバスにおいている隠しパーツです。
EventTick は Add to Viewport された途端走ってしまうので、カットインのアニメーションが再生されるまで我慢するよう、フラグをチェックしています。
これでアニメーションが再生されたら逐次値が横流しされるようになります。

MID～ というオブジェクトノードは マテリアル インスタンス ダイナミックです。事前に Event Pre Constructあたりで作っておくといいです。
![fig19.png](https://qiita-image-store.s3.amazonaws.com/0/212880/52265276-0031-d419-4838-99692fecedcd.png)



カットインの開始イベントはこんな感じです。
![fig17.png](https://qiita-image-store.s3.amazonaws.com/0/212880/a66d0398-1f1c-840d-522c-882761949f92.png)

Event Construct につなごうかと思ったのですが、将来的にキャラの絵を差し替えられるようにしたりViewportへの追加と削除はゲーム開始時と終了時だけの方が処理にやさしい気がしたので、カスタムイベントにしました。

アニメーションの終了は、ビルトイン（でいいのかな）イベントが用意されているのでそちらにつなぎます。On Animation Finished です。
![fig18.png](https://qiita-image-store.s3.amazonaws.com/0/212880/e77a0043-42f0-5dfc-51fb-72a10b3ad06f.png)

ForLoop以降はエフェクトをブループリントで動的に生成して飛ばしているので、それを片付けるようにしています。
生成のときに Do Once を使えばいいだけかもしれないですが・・・。
Add to Viewport と Remove from Parent のタイミングも含めてもうちょっと検証が必要かな。


###エフェクトの生成
エフェクトはスピード感を出すための効果として飛ばしている光っぽいキャラです。
![fig20.png](https://qiita-image-store.s3.amazonaws.com/0/212880/f34d269b-8596-9618-7541-449d60818143.png)
Event Pre Construct で数を決めて、配列を初期化、関数で生成して、配列に入れてます。
![fig21.png](https://qiita-image-store.s3.amazonaws.com/0/212880/7ef8e341-dea6-a60e-21ed-ee6d4e2f857a.png)

生成する際にランダムな高さとサイズを決めています。
![fig22.png](https://qiita-image-store.s3.amazonaws.com/0/212880/aa3fcf19-f2bd-d354-038f-c574fe02112f.png)
サイズをざっくり1.0 ～3.0 のレートを決めたら、そこからサイズとスピード、表示優先を計算していきます。

この関数は、表示範囲を越えた際、次の表示位置とサイズを初期化するためにも呼びだします。


##画面で確認
今回このカットイン用のWidgetは、HUDクラスに管理させてみました。HUDが持っていると、Get Player Controller経由で取得できるのでいいな、と思っているんだけどどうなんでしょうか？この辺まだまだ勉強というか経験不足だなぁ。


実装についての部分は長くなりそうなので、いったんこの辺にしておきます。
Add to Viewport して Inputノードあたりで CutInStart（Custom Event）イベントを呼べば確認できると思います。


##最後に
今回のサンプルでは

- 2Dキャラでカットイン演出をしたい
- アニメーションしてる絵を部分的にマスクしたい
- トーンマップやらポストの影響を受けないカラーで表示したい
- UMGが好き

という方にオススメします。いるのか？

プレイヤーキャラの向こう（奥）に表示することはできないかやってみたのですが、Screen描画のUMGは無理っぽいです。
SceneTexture:CustomDepth を UserInterface のマテリアルに置いてみたら、エラーは出ないけどUMGの描画段階で既に情報が無くなっているようで、なにも取れないうえに、開くだけでクラッシュするマテリアルに変貌を遂げ、作り直すハメに・・・（グラボ関係あったりするのかな？）

プレイヤーの向こうに表示するのは、ポストプロセスマテリアルにすると楽勝な感じですが、アニメーションを作るのが大変そうです。いったんUMGをレンダーターゲットテクスチャにする？
あと、描画キビシくてもカットイン演出のときはひきつっても大丈夫なんじゃ・・・などと考えたりします。

最初のほうで作り方を説明したマスクテクスチャのカタチを変えればいろいろ楽しめます。

まずはUMGでこんなんできましたけど、いかがでしょうか？ 
UMG怖くないですよ、Scaleformでなくても大丈夫ですよとか言ってみたり・・・


明日は[@MozPaca398](https://qiita.com/MozPaca398)さんです