ADX2+UE4で、地形ごとに異なる足音を再生する

# はじめに
アンリアルエンジン4とサウンドミドルウェア「ADX2 for UE4」を連携させ、**キャラクターが踏んだ場所の材質に対応した足音が再生**されるようにします。

AnimNofityとPhysicsMaterialのあわせ技により、キャラクターのアニメーションとしたサウンド再生、状況にあった音の選択を可能にします。


当記事ではUE4.26.1を使用します。基本的にブループリントのみでの実装を想定しています。
ADX2はインディー向けの「LE版」であれば、無料で使用できます。
https://game.criware.jp/products/adx2-le/

# 前提
ADX2 for UE4の導入や基本的な使い方は以下の記事にあります。必要に応じて参照してください。
ADX2 for UE4の導入で、一歩上のサウンド表現を（導入編）
https://qiita.com/SigRem/items/4250925f6d66a4fd287a
ADX2 for UE4の導入で、一歩上のサウンド表現を（実践編）
https://qiita.com/SigRem/items/c089b71c42e898980a46

# 実装

## AtomCraftで足音を準備する
まずはAtomCraftで足音となるキューを準備します。

### マテリアルの用意

マテリアルツリーにドラッグアンドドロップして音源をインポートします。
今回は3種類の足音に、それぞれいくつかのバリエーションを用意しました。
![A01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e8ad081c-d9bd-0940-8721-9ea932f318d1.png)
ファイル名のとおり、コンクリート、草の生えた地面、金属を踏んだ際の効果音となっています。
ランダムに再生することで、何度も再生された際の単調さを解決できるでしょう。


### キューの作成

新規にキューを作成します。「新規オブジェクト」→「キュー『ランダムノーリピート』の作成」を選択します。
![A02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3d64190b-ba8e-b0a0-e272-f7ec95b120b0.png)
「ランダムノーリピート」のキュータイプは、ランダムなトラックが再生される「ランダム」と基本的に同様ですが、**前回と同じトラックは再生されない**という特徴があります。
これを繰り返し、各材質用にキューを用意します。
![A03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/1d56800c-47af-020f-3ceb-087c5dc4803e.png)
マテリアルツリーからサウンドをドラッグアンドドロップし、それぞれ別のトラックに配置します。
![A04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4fc400d4-6830-c34b-51a6-083a7a10de38.png)
再生ボタンを押すと、そのたびに違う音（トラック）が再生されるはずです。
![A05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/23370519-9da6-f48e-bfa8-2a81de52179c.png)

### 3Dサウンドの設定

音に臨場感を与えるため、キューが3D空間上で再生された場合の減衰を設定します。
**キューを選択し**、インスペクターにて「パンのタイプ」を「3Dポジショニング」に変更します。
![A06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/51ae0814-b3b5-b901-fa4a-26852827546c.png)
インスペクター下部で「3Dポジショニング」のボタンを押すことで、距離減衰やドップラー等の設定ができます。
![A11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/66799395-f72b-e6e7-3a9d-9aeab63fc893.png)
実際の聞こえ方を確認するには、セッションウィンドウを使用します。
ツールバーの「表示」→「セッションウィンドウ」から呼び出せます。
![A07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/653fa969-7638-4873-2d19-9c3fb2b7efd3.png)
セッションウィンドウの「3Dポジショニング」を押し、「プレーヤーに3Dオブジェクトをアタッチ」のチェックボックスをONにすると距離による音の変化が確認できます。
![A08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/d393010e-0f11-1951-b315-9df15624dc00.png)
緑色の領域をドラッグすることで音の位置関係を変化させることができます。


### キューシートのビルド
調整ができたら、キューシートをビルドします。
![A09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4ee03a7c-1651-250f-c006-b9f944c20645.png)
![A10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/1586a6d7-7b3a-7117-7d28-3731ac7f108d.png)



## アニメーションによる足音の再生

UE4に組み込み、実際にサウンドの再生と足音の変化を実装していきます。

### キューシートのインポート
コンテンツブラウザにビルドしたキューシート（acfファイル、acbファイル）をインポートします。
![B01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/aed84351-50a7-ce22-3cd8-5d8d01dc1b24.png)
再生するたびに違うトラックが聞こえることを確認します。
![B02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/f5444b61-1e68-9449-9036-1fa7c9dc46f5.png)

### アニメーションにイベントを埋め込む
UE4のスターターアセットに入っているマネキンの走りアニメーションに、足音を再生させるためのイベントを埋め込みます。
アニメーションから呼び出すイベントは。「Notify」（通知）と呼ばれます。アニメーション内の任意のタイミングで足音を鳴らす「Notify」を発火することで、足音の実装に繋げます。

走りアニメーションは、ThirdPersonTemplateからプロジェクトを作成していれば、（プロジェクトフォルダ）\Content\Mannequin\Animationsに「ThirdPersonRun」が入っているはずです。
![B03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/77b33f3d-977b-5cd2-3a8c-c84f5fdbf349.png)

もしテンプレートが異なる場合、コンテンツブラウザの「Add/Import」→「Add Feature or Content Pack」でウィンドウを開き、「ThirdPerson」を「+Add to Project」することでアセットを追加することができます。
![B04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4b9824a5-0e69-9702-ba22-7f779fe374da.png)
![B05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e55ee68e-36d1-b3c9-d9be-4299957a2d4d.png)

「ThirdPersonRun」をダブルクリックして開きます。
再生を止め、タイムラインをドラッグして片足が接地したタイミングまで持っていきます。
![B06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/fa0536b7-0e3c-8c20-e910-090349196503.png)
「Notifies」のトラックで右クリックし、「Add Notify」→「New Notify」を選択します。
![B07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/7104730b-18c2-747f-fd4a-267f10f0d934.png)
左足が接地しているので「FootStep_L」と名前をつけました。
![B08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/6655602a-a74f-59fe-5b8b-b5bee4a0849f.png)
同じようにタイムラインを右足が接地しているタイミングまで動かし、「Add Notify」→「New Notify」から「FootStep_R」を作成します。
![B09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5dbeb165-cbfe-e024-58a2-2eba159756e0.png)
一度作成したNotifyは、「Add Notify」→「Skeleton Notifies」から同じものを作ることができます。
![B10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/83c750fe-7f1b-dcd3-1e15-16abdefedbfd.png)

走りアニメーションはループ再生されるため、これで一歩ごとに右足と左足のNotifyが交互に発火されることになります。
右足と左足でNotifyを分けるのは、足元の材質を判定するために、踏みしめた足を判別するためです。この後の実装を実際にしてみると分かりやすいかと思います。


### AnimNotifyイベントから音を再生する

アニメーションエディタの右上の「Blueprint」をクリックすると、スケルトンに対応したアニメーションブループリントが開きます。
![B11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/49c36bcc-aa93-0e6f-ee09-efd25504b628.png)
「Event Graph」をクリックしてイベントグラフに移動します。
![B12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/21c64238-3a1a-993c-2731-a6a31bec01c6.png)
グラフの空いている場所で右クリックして、検索欄のテキストボックスに「notify」と入力すると、先ほどアニメーションに埋め込んだNotifyが出てきます。
![B13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/d5b0a7b9-5275-aa40-864c-5e329e792b63.png)
これらをクリックし、ふたつのイベントを作成します。
![B14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/515a42b4-8de5-8073-4fc6-9f20d26e23d4.png)

ADX2LEにはバージョンアップにより新しく追加されたノード**PlaySoundForAnimNotify**があります。これはAnimNotifyから起動されるサウンドを想定した機能を持っていますが、キューの初期パラメータや後天的な挙動の変動ができません。今回は足音にセレクタやAisacコントロールなどの変動する機能を使っていないため、このノードを使用します。

**PlaySoundForAnimNotify**をイベントから繋げます。再生するキューは、ひとまず適当なものを設定しておきます。
![B15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9c35ba3b-a3b8-8876-3fee-704ee40f4693.png)
キャラクターから足音が聞こえるようにするには、「Attach to Component」にキャラクターのメッシュなどのコンポーネントを指定してあげる必要があります。

キャラクターのメッシュを取得してみましょう。
イベントグラフの別の場所で右クリックし、**Event Blueprint Begin Play**というイベントを作成します。
![B16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9e274a48-000b-994d-8101-46d104e50691.png)
**Try Get Pawn Owner**ノードを配置し、「Return Value」ピンから線を引き出し、**Cast To （キャラクタークラス名）**を作ることでキャラクタークラスにアクセスできるようになります。
![B17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/47fa38d2-cd2d-9e51-bbc6-ee3f6c56dfa2.png)
「As （キャラクタークラス名）」の青いピンを右クリックし、「Promote to Variable」で変数化します。
![B18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/6a9fdfb9-8bb6-1303-5bf7-2325214e64b3.png)
新しく変数が作られるので、適当に名前を付けます。今回は「OwnerChar」としました。
![B19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/d14e42ab-bd2d-1fbc-adbb-c70427d5ead7.png)
**Get OwnerChar**→**Get Mesh**ノードでキャラクターのメッシュコンポーネントが取得できるため、それぞれ右足と左足の**PlaySoundForAnimNotify**に繋ぎます。
![B20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e392b195-01d2-7756-0271-b299a3a14ef2.png)
テストプレイしてみると、走っているキャラクターから足音が鳴っているはずです。
![B21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/1a7310d2-f021-7da7-7e0c-98c4d8714c10.png)


### PhysicalMaterialを作成する
PhysicalMaterialを使ってマテリアルごとに足音を設定できるようにしてみましょう。
コンテンツブラウザの任意の場所で右クリックし、「Physics」→「Physical Material」を選択します。
![B22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/79e09c77-fa19-2d2c-1b53-397694074995.png)
「PhysicalMaterial」を選択した状態で「Select」をクリックします。
![B23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5e32463b-0d85-c3b5-b54c-13a7ffb2da22.png)
今回は「Concrete」「Grass」「Metal」の3つのPhysicalMaterialを作りました。
![B24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/ed22459b-9fd5-3d4b-148f-0116b87bbf6e.png)
PhysicalMaterialを開けば、摩擦などの設定をすることも可能です。


### トレースによってPhysicalMaterialを取得し、音を変化させる

アニメーションブループリントのグラフに戻ります。
直接開く場合、コンテンツブラウザの「ThirdPerson_AnimBP」をダブルクリックします。
![B25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/c667fc49-b1ba-75ef-6f47-ffb3ae38dd18.png)
今回は足元の材質の判別を、足からレイ（線）を飛ばして衝突した箇所のPhysicalMaterialを取得する方法で行います。
![B44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/f1580bc5-badf-486c-c832-74887152fa1c.png)

**LineTraceByChannel**ノードを配置します。
![B26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4d2659f2-73b8-fac8-93eb-0a6cc7fa820e.png)
![B27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/6cb73b3f-4711-d5bb-c496-142d0fda57a1.png)
キャラクターの足から地面へ向かってトレースを飛ばすため、開始地点はキャラクターメッシュの足ボーンを参照します。
**Get Socket Location**でボーンまたはソケットの座標を取得できます。**LineTraceByChannel**の「Start」ピンに繋ぎます。
マネキンのメッシュの場合、左足のボーンは「foot_l」です。
![B28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/98eb1205-c2ad-7abf-f119-e70f65a545a8.png)
トレースの終端は足ボーンの少しだけ下なので、Z軸を「-30」した座標を指定します。
![B29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/f04da05b-5970-b635-75d7-781abc17cbaa.png)
**LineTraceByChannel**の「Return Value」からはトレースがヒットしたか、「Out Hit」からはトレースがヒットした場所の様々な情報が返されます。それぞれ**Branch**と**Break**ノードを繋ぎます。
![B30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/cf2eb43b-556a-2c33-630d-e5588c2e5430.png)

「Phys Mat」ピンからはトレースがヒットした場所のPhysicalMaterialが取得できます。
今回欲しい情報はPhysicalMaterialの名前だけなので、**Get Object Name**ノードを配置します。
![B31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/1f0a195f-7d2d-413b-7c7d-6954ada9a906.png)
PhysicalMaterialの名前ごとに処理を分岐させたいので、**Switch on String**ノードを使います。
![B32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3defc7d7-28a4-4956-4077-f060f95b9cbe.png)
それぞれが対応する足音を再生する**PlaySoundForAnimNotify**ノードに繋げます。
![B33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/63879f43-2957-9650-d296-a2f0e7edad6e.png)
「Attach to Component」ピンにキャラクターのメッシュを参照させます。
![B34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/852e0cac-1031-1963-843d-8f020204191e.png)
右足についても、同じように処理を組みます。
![B35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/66a6b5fb-a47b-9bcb-3ec7-1745ca9067b6.png)
ノードをコピペしても大丈夫ですが、右足のボーン名「foot_r」を指定することを忘れないでください。
![B37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/739ac3b8-523e-29dd-40f0-4f23a761699b.png)
**LineTraceByChannel**ノードの「Draw Debug Type」を「For Duration」にしておくと、トレースが視覚化されるためテストに役立ちます。
![B36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5dfa5832-7633-6490-d1ae-fdca0bc11218.png)

レベル上の地形にPhysicalMaterialを指定します。
メッシュを指定し、Detailsパネルにて「Phys Material Override」で設定することもできますし、
![B38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/a95c251e-24c3-251c-020d-d92bc48a9d7e.png)
マテリアルインスタンスにて「Phys Material」で設定することもできます。
![B39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/84530801-e320-ddba-334c-7351d53b0948.png)
両方設定した場合、前者が優先されます。

テストしてみましょう。キャラクターが走ると足からトレースが視覚化された線が出現します。
ヒットした場所で四角のマーカーが出ます。
![B40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/382f9090-df2d-10aa-eee0-c85d2347eae1.png)
![B41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5f342f78-8c64-9e30-4712-d5206ae18416.png)

材質の異なる場所では違う足音が再生されるはずです。
![B42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/182d8784-6ad1-f24d-df3d-681a0767d59c.png)

補足ですが、**Switch on String**ノードの「Default」ピンに再生処理を繋いでおけば、PhysicalMaterialが未設定や例外の地形でも鳴らす足音を指定できます。
![B43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/815f248d-6303-c42e-4869-cecdb378039e.png)