ADX2 for UE4で作る、銃弾がプレイヤーを掠める表現のサウンド

# はじめに
アンリアルエンジン4とサウンドミドルウェア「ADX2 for UE4」を使って、FPSやTPSで見られる「銃弾がプレイヤーを掠める」サウンドを実装します。

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

記事執筆時点のADX2 for UE4のSDKバージョンはv1_29です。

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


# 実装

## AtomCraftで効果音を構成する

### マテリアルの用意
今回は銃弾が掠める音を3種類用意しました。これらをランダムで再生し、音が連続して再生されないようにします。
音声データをマテリアルツリーにドラッグアンドドロップしてインポートします。
![A01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/2b11dc59-2840-baa6-9e6b-e45c42f050b5.png)
実際にゲームに実装する際はこれ以外にも発射音や着弾音が必要になりますが、記事では割愛します。

### キューの作成

新規にキューを作成します。
ワークユニットツリーのキューシートを右クリックし、「新規オブジェクト」→「キュー『ランダムノーリピート』の作成」を選びます。
![A02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3a0b782d-fd82-02f9-edd6-2cd6b2302717.png)
「ランダムノーリピート」タイプのキューは再生するたびにランダムなトラックが呼び出され、また連続で同じトラックが再生されないという特徴があります。

キュー内にトラックを分けた状態でマテリアルを配置します。
![A03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/6999beb7-d203-2a1b-f4d8-996af783ff13.png)
**キューを選択した状態で**、インスペクターから「パンのタイプ」を「3Dポジショニング」に設定します。
![A04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/b8be18e6-36ee-972e-90b0-84fd7f44fb67.png)
再生するたびに異なるトラックが流れることを確認しておくといいでしょう。

また、「ピッチランダム幅」を少し上げて、再生されるピッチをランダムで上下するように設定します。
こうすることで同じ効果音でも流れたときの印象が変わり、音を繰り返し再生しても違和感が生じにくくなります。
![A05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/46061ded-fcd4-efec-aab4-691cbe8bf857.png)

### 音声テスト

ゲーム中で聞こえる音声のテストをします。
ツールバーの「表示」→「セッションウィンドウ」をクリックしてセッションウィンドウを呼び出します。
![A06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e71301c3-b2e6-13d4-9bab-0baca556acbf.png)
セッションウィンドウの下部にキューリストがあるので、キューをドラッグアンドドロップして登録します。
![A07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9f4059a9-0613-2864-ebbd-d2603a3b544c.png)
最上部の「3Dポジショニング」をクリックして、3D音響のテスト機能を有効にします。
![A08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/729a4be8-1ab9-96f4-a3d1-b0f06a9ac52c.png)
「プレーヤーに3Dオブジェクトをアタッチ」にチェックを入れ、緑色の領域をドラッグしてサウンドを動かします。
再生してみて、音の聞こえる位置が動く様子を確認してみましょう。
![A09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/74fccc41-4488-e0ed-b26f-413e92a20cdb.png)


### キューシートのビルド

聞こえ方が大丈夫そうならキューシートをビルドします。
![A10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/d3921937-b02d-f8f5-7f30-c54f51bb71f1.png)
![A11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/91313041-2356-825e-48e0-bc9a7156d904.png)



## UE4で簡単な銃弾を作成する

UE4のエディタに移動します。

### キューシートのインポート

銃弾を作成する前に、キューシートを忘れずにインポートしておきます。
ビルドしたacf、acbファイルをドラッグアンドドロップします。
![B01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/c3c84939-f552-3733-7d81-72e7ae217381.png)
「Edit」→「Project Settings」を開き、
![B02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/563bce6f-e40d-1c7a-0d31-4e71930a349d.png)
「CriWare」タブにて「AtomConfig」にインポートしたacfファイルを指定します。
![B03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/68f715cb-f1e5-80e3-1614-00e6a79ec3fe.png)


### 銃弾用のBPを作成

銃弾となるブループリントアクターを作成します。
コンテンツブラウザの適当な場所で右クリックし、「Blueprint Class」を選びます。
![B04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/27548794-c3e6-71fb-3abe-4a5d0c23d45c.png)
親クラスは「Actor」です。
![B05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/370a056c-a92c-84a2-0fc9-8c8a190ae195.png)

作成したアクターをダブルクリックして開き、「Sphere」と「Arrow」コンポーネントを追加します。
![B06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/a9c63847-f613-a3c2-ee49-d768ebc228c8.png)
「Sphere」は「SphereCollision」ではないほうです。メッシュ指定がされているだけで、内部的にはStaticMeshコンポーネントになります。
![B09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5eac4f2f-062b-68a9-1b03-233a44ebdfda.png)

Arrowコンポーネントはテスト用に銃弾の進行方向を分かりやすくするために置いているので、Detailsパネルにて「Hidden in Game」のチェックを外します。これでゲーム再生中でもArrowコンポーネントが見えるようになります。
![B07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/42a64d12-a438-ad57-e30e-245a1439a677.png)
デフォルトだとSphereが大きいので少し縮めます。
レベルに配置すると大きさはこんな感じです（実際に置く必要はありません）。
![B08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/6e1a8726-3138-6068-a7d6-03515f513ed8.png)


### トレースチャンネルの用意

当たり判定の処理を作る準備として、トレース用のチャンネルを作成します。
プレイヤー用のトレースチャンネルがある場合はこの工程は省いて構いません。
プロジェクト設定を開きます。
![B15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9fd8c793-d412-5d89-044f-8c5551378b20.png)
「Collision」ページにて、「New Trace Channel...」のボタンを押してチャンネルを追加します。
![B16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/eda7bdf3-52c5-6cbe-a843-29de3bd37019.png)
チャンネル名は「Player」とし、「Default Response」（オブジェクトがデフォルトでとるリアクション）は「Ignore」にしておきます。手動で設定したオブジェクト以外は、このトレース判定を無視することになります。
![B17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4a869d4e-82d8-5dca-537f-059aa202d307.png)
プレイヤーキャラクターのブループリントを開き、メインとなるコリジョンを選択します。通常はCapsule Componentなどです。
Detailsパネルの「Collision Presets」を「Custom」にし、新しく出現した「Player」の場所で「Block」にチェックを付けます。
![B18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/fcd5583d-f441-0c51-879e-6d2662e4e2dd.png)
これでプレイヤーキャラクターだけは銃弾の当たり判定に反応することになります。


### 銃弾の推進

作成した銃弾アクターに戻ります。
**Event Tick**から処理を開始し、**Sequence**ノードを置きます。
これは今回処理を整理するために使用していますが、上のピンから処理が順番に行われるノードです。
![B10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/8538a38a-2f92-5196-7f0d-1e14e9b96a6a.png)
**AddActorLocalOffset**ノードでお手軽に銃弾を飛ばすことができます（Projectile Movement Componentも使用できますが、設定項目が多いため今回は簡易な処理にしています）。
![B11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/f46f0b3d-5d70-29c4-981b-a8ecb3d112a7.png)
黄色い「Delta Locaiton」を右クリックし、「Split Strcut Pin」を選択します。
![B12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/853c355a-13e8-bd7d-fc64-5f7c097e6ec9.png)
3つのfloatピンに分かれるので、一番上の「Delta Location X」を右クリックして「Promote to Variable」を選択します。
![B13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/642d6d7b-6325-c032-e8f2-7048d11ec79d.png)
新しくfloat変数が作られます。これが銃弾の推進スピードになります。
![B14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3a7fff33-d0f9-4e07-6589-4e41fdaf1ff8.png)


### トレースによる掠め判定、サウンドの再生

**Sequence**ノードの下側には銃弾の当たり判定（今回は掠め判定）を作っていきます。
判定の肝は**MultiSphereTraceByChannel**ノードです。
![B19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/b964fb42-14f7-0334-198f-fec109236316.png)
球形の判定を展開するノードです。今回はアクターを中心に単純な球で展開したいので、「Start」と「End」ピンには**GetActorLocation**ノードをつなぎ、半径となる「Radius」にはとりあえず「150」を入力します。
テストに便利なので、「Draw Debug Type」は**「For One Frame」**にしておきましょう。
![B20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/768f125e-090a-c250-f1a3-84d6265c1e3f.png)
**MultiSphereTraceByChannel**の後に**For Each Loop**ノードを置きます。
![B21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3034478a-5b01-d553-af30-323393379308.png)
次の画像のように**Branch**ノードを挟み、トレースにオブジェクトが引っかかったら次の処理にいくようにします。
![B22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/dcbe82d2-9506-3d8b-8f61-03ed38fe3789.png)
**For Each Loop**ノードの「Array Element」ピンから線を伸ばし、「Break Hit Result」を選択します。
![B23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/bedd766e-1d2b-2809-c7d3-1e995e058290.png)
次のようにつなげば、トレースが感知したオブジェクトがプレイヤーキャラクターかどうかを判定できます。
![B24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9f0a4653-abc2-5f0b-39d5-e2ae07474925.png)
もしプレイヤーだった場合、**Add Atom Component**で銃弾が掠めた際のサウンドを再生します。Atomコンポーネントはこのアクターに追加されるため、3Dサウンドとして設定されていれば銃弾がプレイヤーの後方に飛んでいった際も立体的に聞こえてくれるはずです。
この処理がひとつの銃弾に対して連続して実行されないよう**Do Once**ノードを挟みます。
![B25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/fcac5cad-ac0d-0271-2ffa-466acc2ab424.png)
**Add Atom Component**ノードを選択すると、Detailsパネルにてサウンドの設定ができます。
忘れずにAtomCraftで構成したAtomキューを指定しましょう。
![B26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9ccdbe7c-a673-1414-3a9d-5bdcaabd096f.png)
ノードの全体図はこんな感じです。
![B27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/790931c3-2eb2-6764-ca1b-f4589d7e912f.png)


### テスト用にスポーンする

銃弾は完成しましたが、発射機構がないためレベル上で直接スポーンできるようにします。

レベルに「TargetPoint」アクターを配置します。「Place Actors」のパネルにあります。
![B28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/afa12965-d714-7e8e-feac-944ce863df33.png)
レベルブループリントを開きます。
![B29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5f537a39-9b74-e94e-075c-584c73a0fedb.png)
キーが押されたことを判定するイベント、**Input Key**イベントを配置します。今回はRキーにしました。
![B30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/d94f730d-ef7f-25e9-874c-d9205d0e16d7.png)
**レベル上で「TargetPoint」アクターを選択し**、レベルブループリントで右クリックし「Create a Reference to TargetPoint」でリファレンスノードを作ります。
![B31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/2fe00679-b5d1-c9f9-15d6-c69de5e909b1.png)
**Spawn Actor from Class**ノードでアクターをスポーンします。
![B32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5e8d21e9-3704-aa48-1b79-7f52256f7e76.png)
スポーン先は**Get TargetPoint**から線を伸ばし**Get Actor Transform**で「TargetPoint」アクターの座標や回転を代入します。
![B33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/344622b6-2cd1-1729-74cf-800d3bc854dc.png)
銃弾アクターのスピードを上げておき、トレース範囲も拡大します。
![B34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/eb22d7f3-2fcb-df7f-9b1a-3c86c88279cf.png)
ゲームを再生し、Rキーを押すと「TargetPoint」アクターの位置から銃弾が発射されます。近くまで行きトレース範囲に重なると、銃弾が掠める音が発射されるはずです。
![B35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/a0e104a6-69b7-da31-1af1-76f64c346219.png)

AtomCraftでパラメータを追加すれば、音のくぐもり方や距離による減衰が細かく設定できます。
こだわりのサウンドを作り、臨場感のある戦場を作ってみてはどうでしょうか。