ADX+UE4で、BGMに紐づけて多様なサウンドを再生する

# はじめに
アンリアルエンジン4とサウンドミドルウェア「ADX2 for UE4」を使って、BGMの特定のタイミングに紐づけて自動的にサウンドを再生できるようにします。

また、ここで再生されるサウンドはゲーム中の状況により変化をもたせられるので、
「ベースは同じだが、エリアにより旋律の異なるBGMを再生できる」
「BGMの開始時に流れるサウンドが異なり、第一印象が変化する」
「戦闘終了時にBGMの再生が終わった際の演出にバリエーションをもたせる」
といったシチュエーションが演出できます。

分岐にはAtomCraftの「ゲーム変数」機能を使用します。

当記事では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で効果音を構成する

### マテリアルの用意

![A01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4dd67981-8f6a-d154-f082-08d77c16f6b1.png)
今回はベースとなるBGM（BGM_Base）を用意し、さらに
- BGMの開始と同時に再生するキック音を2種（BGM_PhraseA,B）
- BGMの途中で流れるフレーズを2種（SE_KickA,B）
追加してみました。


### キューの作成

まずはBGM用のキューを作成します。
キューシートを右クリックし、「新規オブジェクト」→「キュー『ポリフォニック』の作成」を選択します。
![A02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/f34dd21f-e0ec-5360-792c-cea4a247a904.png)
作成したキューに名前をつけ、マテリアル「BGM_Base」をドラッグアンドドロップしてトラックを作ります。
![A03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/82a6abc4-0c17-852b-224a-fd0f2eddc700.png)

次に分岐するサウンド用のキューをふたつ作成します。
キューシートを右クリックし、「新規オブジェクト」→今度は「キュー『スイッチ』の作成」を選択します。
![A04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/bb27c57f-a318-56ca-07c0-3e84408d94fe.png)
作成したキューにフレーズ用のふたつのトラックを入れます。
![A05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/8692c6bd-a953-3cbb-0f0a-b8796fc93278.png)
同じようにキューを作成し、キック用のマテリアルを入れてトラックを作ります。
![A06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/26f6f31d-ae1a-e190-0612-a58bca3f923a.png)


### ゲーム変数の設定

サウンドを分岐させるため、ゲーム変数を作成します。
プロジェクトツリーの「ゲーム変数」を右クリックし、「新規オブジェクト」→「ゲーム変数の作成」を選びます。
![A07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/acdf1fb9-0ded-fa37-65ad-ea3c5be1fce8.png)
新しく作られたゲーム変数に分かりやすいよう名前をつけておきます。
![A08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e7afdb8a-9542-e9fe-f88f-5f3c77aaed89.png)

フレーズ用のキューを選択し、インスペクターにて「スイッチ」のボタンを押すとトラック分岐用のメニューが現れます。
![A09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/72dee307-17da-8a48-8b36-4e083dcf76b2.png)
スイッチ変数に先ほど作成したゲーム変数を設定します。
![A10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/45bad5b2-c95b-12c1-e7af-12f995c8907c.png)
デフォルトでは変数による配分が等分にされており、選択肢がふたつの場合は0.5以下であればひとつめのトラックが、0.5超であればふたつめのトラックが再生されます。配分を任意で入力することも可能です（合計が1.0になるようにしてください）。
![A11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/60d6d696-b0b5-b754-2e15-4f001cafa2b6.png)
プロジェクトツリーの中のゲーム変数を選択し、インスペクターにて「初期値」を変更すると、数値が変わった場合の聞こえ方をテスト再生することが可能です。
![A12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/30da76eb-43fe-4fc3-62eb-62c74ebb6f80.png)
同様にキック用のキューにもゲーム変数による分岐を設定します。
![A13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/1291db0b-c593-fd71-5356-06324f47e413.png)


### アクションの設定

キュー内の任意のタイミングに埋め込み、他のサウンドを呼び出したりする機能を「アクション」と呼びます。
ベースとなるBGMのキューにアクションを設定していきます。
**ベースとなるキューを選択して**、トラックリストの空欄で右クリックし「新規オブジェクト」→「アクショントラックの作成」を選択します。
![A14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3c23265e-fccd-f3a1-db7c-b4144e5b3369.png)
新しくアクショントラックが作られます。アクショントラックは対象となるオブジェクトがないと機能しないので、フレーズ用のキューをワークユニットツリーからドラッグアンドドロップして指定してあげます。
![A15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/666f97f1-d147-71e0-76c2-54cc34a147bd.png)
同じようにふたつめのアクショントラックを作成し、こちらにはキック用のキューを指定します。
![A16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/2fcca673-55d1-8755-1b84-53e911645fcd.png)
アクショントラックを選択すると、インスペクターでトラック名が入力できるので識別用に名前をつけておくといいかもしれません。
![A17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e30641dd-e62e-f7c2-71e3-32f511693e83.png)
アクショントラックの横のタイムライン上で右クリックし、「新規オブジェクト」→「スタートアクションの作成」を選択します。
![A18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/af43dfa5-2cb3-8fd3-5f66-aa3ad9dbb522.png)
キューの呼び出しを行うマーカーが設置されるので、任意の位置までドラッグして持っていきます。
BGM開始時のキックを呼び出すためのマーカーなので、今回はタイムラインの最初に配置します。
![A19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/f522984c-4941-abf2-2dae-9d7f00d59fdd.png)
フレーズ呼び出しはBGMの途中で呼び出したいので、5小節目に作成しました。
![A20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9d6e73a3-a665-11d4-ff11-2e8288e5daf6.png)
BGMのタイミングに合わせてマーカーを設置したい場合、時計のボタンから「タイムベースの編集」を行いビートに合わせた表示にしておくといいでしょう。
![A21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e1f35616-55c8-f70b-ccd0-1f14ed5778d6.png)
BPMを設定すればOKです。
![A22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5557183a-9a69-69b6-ef3d-341d59eedc02.png)

この状態でテスト再生すると、AtomCraft上でもサウンドが呼び出されます。
ゲーム変数の初期値を変更すると、やはりサウンドが分岐し違った音が流れるようになります。


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

ここまでできたらキューシートをビルドし、UEに持っていく準備をします。
![A23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e39bcb96-74bc-881a-5802-f391768f8df0.png)
![A24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/83db3936-46b4-00f2-e995-e443d7a5e213.png)



## UEでの実装

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

AtomCraftでビルドしたキューシートをインポートします。
acbファイル、acfファイルともにコンテンツブラウザにドラッグアンドドロップしておきます。
![B01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/b504941b-fafb-cdd7-8393-26a1490466fe.png)
![B02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9bfc8ed0-107f-b8a6-d154-40c7f4ff9ea0.png)
ツールバーの「Edit」→「Project Settings」からプロジェクト設定を開き……
![B03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/276ca0c4-bebc-86e5-56cc-84d0e08b5981.png)
CriWareタブの「Atom Config」に、インポートしたacfファイルを指定します。
![B04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/917e34c3-8bf4-ac5c-dbbc-3cceb4d4dc2e.png)

**ここで一度再起動しておきます。**




### BGMの再生

レベルブループリントからBGMを再生してみましょう。
「Open Level Blueprint」からレベルブループリントのエディタを開きます。
![B05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/cebc5544-dfc8-6aa5-6ce8-5db843c67eb5.png)
再生に必要なのはこれだけです。
**Spawn Sound 2D**ノードにはベースとなるBGMのキューを指定します。
![B06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4104469a-16d3-61f3-47d8-07b1cf150649.png)

ゲームをテスト再生すると、AtomCraftでのプレビューと同じようにBGMが再生され、またアクションによるサウンド呼び出しも機能しているようです。


### ゲーム変数によるサウンド分岐

仕上げにゲーム変数を変更し、サウンドが変わるか確認してみます。

Rキーでの再生後に**Set Atom Game Variable**でゲーム変数を「0.0」に設定します。
同じようにTキーでも再生を開始し、こちらでは**Set Atom Game Variable**でゲーム変数を「1.0」に設定します。
![B07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/78ef91c5-7d32-5b30-9483-70b90e4e80c5.png)
RキーとTキーでそれぞれ違うバリエーションのアクションが呼び出されることになります。

このままではキーを押すたびにBGMが重なってしまうので、再生開始する際にBGMを止める処理を入れてみましょう。
（テスト用なのでここからは実装しなくても大丈夫です）
**Spawn Sound 2D**ノードの青いアウトプットピンを右クリックし、「Promote to Variable」でAtomキュー（正確にはAtom Component）を変数化します。
![B08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/772bee7a-1288-fb72-6500-d27c8efd6f4f.png)
**Set**ノードが作られるので、処理の最後に置きます。
![B09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/56e9694e-7a8a-3477-8b2d-4bb67fb0ef93.png)
再生開始時に再生中のBGMが有効であれば**DestroyComponent**し、新たに再生を開始する処理になりました。
![B10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/7cd7c8f1-5693-0fec-5dd0-27b128980dfc.png)
この処理ならテストのたびにいちいちゲームを再生しなおさなくて済みます。


## 補足

「アクション」による機能は単なる再生だけではなく、パラメータを変更したり別の方法でサウンドを分岐させたり、といったこともできます。
呼び出したトラックの性質も受け継がれるため、演出のために試しておくといい機能になるでしょう。