UE4でホワイトボードを作る

#はじめに
こちらの動画（[Unreal Engine 4 Tutorial - Making a Usable Whiteboard](https://youtu.be/TVZS7BHSEkY)）を参考に、以下のようなホワイトボードを作ったので、復習も兼ねて記事を書いてみることにしました。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">レンダーターゲットでホワイトボード作った！<br>LineTraceとかの結果からマテリアルを動的に変化させられるから、歩いた所だけ無くなる雪とかもこんな感じで作るのかな？<a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://t.co/QIHjo3cSaI">pic.twitter.com/QIHjo3cSaI</a></p>&mdash; Naotsun (@Naotsun_UE) <a href="https://twitter.com/Naotsun_UE/status/1181931824282398720?ref_src=twsrc%5Etfw">October 9, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#どんなことしてるの？
まず、ホワイトボードを作るにあたって大まかな処理の流れを見てみましょう。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/120e1332-532c-6889-0ae0-2d3e9e2442ba.png)

つまり、線を書いているように見えますが無数の円の連なりで線のように見せているということです。

#つくってみる
今回は動画と同様、FirstPersonテンプレートで作成します。また、StarterContentのアセットを使用するので追加しておきましょう。

##レンダーターゲットを作成
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/cb2b6759-9532-80d2-2524-d48888346128.png)
まずは、コンテンツブラウザ右クリックから「Material & Textures」の項目から上の画像のアイコンの「Canvas Render Target」を作成します。名前は「RT_WhiteBoard」としておきます。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/78581c26-fc3f-77a4-59e1-75a803c0195b.png)
作ったアセットを開き、Deteailsタブの「SizeX」と「SizeY」を512にしておきます。
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/f76cc43e-391c-8f46-47f8-e6a74e47785e.png)
次に、Project Settingsを開き上の画像の項目にチェックを入れます。
検索ボックスで「UV」と打ち込むと出てきます。
![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/ff907745-48c2-afea-edc8-f74724794a41.png)
この項目にチェックを入れないと後で使用するこちらのノードが正常に動作しません。

##マテリアルを作成
まず、コンテンツブラウザ右クリックからマテリアルを作成します。名前は「M_WhiteBoard」としておきます。
![6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/16d71804-c4ed-3876-7f54-9be33916493e.png)
このようにノードを組みます。「Texture Sample」には先程作成したレンダーターゲットを指定します。
「PenColor」の値を変更することで、ペンの色を変えることができます。また、その上の3Vectorが背景色にあたります。今回はホワイトボードを作るので白色で固定にします。
これでホワイトボード側のマテリアルは完成です。

次にマーカーの役割をするマテリアルを作成します。名前は「M_WhiteBoardMaker」としておきます。
![7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/b3cb8854-0037-9e8a-1283-703e7a43752f.png)
![8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/0eb2b547-3dcf-cdf0-d16c-17d4536ede6e.png)
このようにノードを組みます。「DrawSize」の値を変更することで線の太さを変化させることができます。「DrawLocation」にはUVのどの地点に円を描画するのかという座標の情報を渡します。
これでマーカーの役割をするマテリアルは完成です。

##UVについて
ここで「UVの座標ってなんだ？」とか「さっきもUVなんとかの設定とかしたなぁ...」とか思う方もいるのではないでしょうか。
ブループリントの作成に入る前に先程のノードを交えて説明しておきたいと思います。
![9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/5324ba51-8d92-b015-bb2f-ad53f57b5d59.png)
UV座標とは例えば先程のテクスチャの左上が原点だとすると、右下は(512 , 512)ではなく(1 , 1)となる座標です。例えば真ん中であれば(0.5 , 0.5)となります。
![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/ff907745-48c2-afea-edc8-f74724794a41.png)
そして先程のこのノードですが、ライントレースなどで得られた結果(Hit Result型)からUV上の座標を取得するノードになります。つまりこのノードのおかげでUV座標上の正確な位置が取得できるということです。

これを踏まえてライントレースをしたりするブループリントを組んでいきましょう。

##ホワイトボードアクターを作成
まず、コンテンツブラウザ右クリックからアクタークラスのブループリントを作成します。名前は「BP_WhiteBoard」としておきます。
![10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/6b8ba7b5-8a13-fd4b-66d4-bbd8fec1be63.png)
Static Meshコンポーネントを追加し、Deteailsタブからスタティックメッシュとマテリアルを設定します。今回はStarterContentの「SM_GlassWindow」を使用します。
StarterContent入れてなかったという方はコンテンツブラウザの「Add New」から「Add Feature or Content Pack to the project」からStarterContentを追加しましょう。
![14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/0fd1dbe3-4c68-9f5a-bd78-bed76b20a4a2.png)
設定したスタティックメッシュ(今回はSM_GlassWindow)を開き、「Collision Complexity」を「Use Complex Collision as Simple」にしておきます。これも正確なUV座標を取得するために必要な設定です。
複雑なコリジョンなどについてはヒストリアさんがわかりやすい記事を公開されています。
[[UE4]コリジョンの作成方法のまとめ](http://historia.co.jp/archives/10622/)


![11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/061cae73-fb4d-78fb-c526-ffb3b64064db.png)
このようにノードを組みます。「WhiteBoardMaker」変数はMaterialInstance型です。また、DrawOnWhiteBoardイベントの引数「LocationToDraw」はVector2D型です。
BeginPlayの時には動的にマーカー用のマテリアルを変化させるので、ダイナミックマテリアルインスタンスを作成しています。その次の「ClearRenderTarget2D」関数ではレンダーターゲットの初期化を行っています。書いたものを全削除するような機能を付ける際はこのノードを使うとよさそうです。
DrawOnWhiteBoardイベントでは、イベントの引数がVector2D型、「SetVectorParameterValue」関数の引数はLinerColor型なので
Vector2D --> Vector --> LinerColor
という風に変換しています。そして次の「DrawMaterialToRenderTarget」関数でレンダーターゲットにマテリアルを書き込んでいます。

##書き手の処理を作成
今回はテンプレートの「FirstPersonCharacter」に処理を追加します。
![12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/2f84032a-335e-a5da-c66a-e709c79b9fd7.png)
ボタンを押しているかの真偽値を格納するbool型の変数を作成し、このようにノードを組みます。変数名は「IsDrawing」としておきます。これでボタンを押している間だけtrueになる変数ができました。
![13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/b663fbd6-56cc-d1e1-e059-d2d9ec33b926.png)
次にTickイベントでこのようにノードを組みます。ここでは、ボタンを押している間、視点カメラからライントレースをして当たったアクターがホワイトボードならUV座標を求めて「DrawOnWhiteBoard」イベントを呼び出してあげます。
注意点として「LineTraceByChannel」関数の「TraceComplex」にチェックを入れておきましょう。これをしないとせっかく複雑なコリジョンを使用しているのにライントレースでは簡易的なコリジョンを使用することになります。

##ホワイトボードを配置
ホワイトボードアクターをレベルに配置して、それに向かって右クリックを押すと線が書けます。
![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/c58dd3fa-873a-7001-8cd6-8aa87d3291c6.png)

#おわりに
VRで作れば色んな色でお絵かきできるだけでも面白いものになりそうです。
この機能を使うと、移動した跡のつく雪やキャラクターのメッシュの撃たれた箇所に傷をつけるなど色々なことができそうですね。
また、この方法の問題点として冒頭で説明した通り円を連ねて線に見せているため、すばやく線を引くと下の画像のように途切れてしまいます。
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/251dcf5a-d84c-e508-a6ed-8342a1ca48eb.png)
~~何か良い対策をご存じの方が居ましたら、教えて頂けると嬉しいです！~~

綺麗な線を引けるように改良しました！
>[UE4でホワイトボードを作る -改-](https://qiita.com/Naotsun/items/1a308a041836c5f88f0e)

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/bab05a44-3a2f-59d3-43ec-7be71c290dfb.png)
#サンプルプロジェクト
今回作成したプロジェクトはこちらからダウンロードできます。
https://github.com/Naotsun19B/WhiteBoard