ADX+UEで、一定範囲内の音のパラメータを一括で変更する（ランタイム）

# はじめに
アンリアルエンジン4とサウンドミドルウェア「ADX2 for UE4」を使って配置したサウンドについて、**指定した一定範囲内にあるサウンドのパラメータを一括で変更**する実装についてです。

想定されるシチュエーションとしては
- 「街の路地裏に入ると、大通りで鳴っている音を一括で減衰させる」
- 「キャラクターが『範囲内の音を消す魔法』を使って隠密行動をとる」
- 「大きなクリーチャーの轟音で周りの音がかき消される」

などの演出が考えられます。

ひとつひとつリファレンスを取得してパラメータを代入するとどうしてもノードがかさみがちですが……
![D01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/8d3d645d-8069-2c6a-5c5d-d988e3f309c4.png)
当記事の実装ではある程度スマートなグラフに抑えることも可能になります。
![D02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/bfb29ee4-b221-358d-e8b5-55f09bd1857f.png)



# 前提

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

なお、最近ADX2からADXへ名称が変更になりましたが、ツール構成は変更ありません（2がないから古いほう、というわけではありません）。

記事執筆時点のADX 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」で効果音をビルドしていることが前提になります。
AtomCraftの使い方については、上記の導入編、実践編を参照してください。

## 専用のアクターの実装

### キューの再生用アクターを用意する

お手軽にサウンドを配置、管理するためのアクターを作ります。
コンテンツブラウザの空欄で右クリックし、「Blueprint」を選択。
![A01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/ed782a0f-002a-271a-1233-87d8119a8390.png)
親クラスは「Actor」にします。
![A02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/2dbff248-69d3-37ae-291e-322f4fb1418f.png)
アクター内にふたつコンポーネントを追加します。
サウンドを再生するための「Atom」コンポーネント、範囲内にあるサウンドを一括で感知するためのコリジョン（当たり判定）となる「StaticMesh」コンポーネントです。
コリジョンさえ設定されていれば、メッシュは何でもかまいません。
![A03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/cc52f52e-beb3-3fe0-fd0e-49295ea43f67.png)

### コリジョンの調整
テスト用にはそのままでいいのですが、実際に運用する際にはプレイヤーやキャラクターのコリジョンと干渉しないよう、コリジョン設定を調整してあげると良さそうです。
アクター内でStaicMeshコンポーネントを選択して、Detailsパネルの「Collision」で設定できます。
![A07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/b22bd7d6-1263-5d11-5bd2-129df8b4ac02.png)
**この設定によっては後述の処理がうまく動かなくなったりするので、先に一通りのテストを終えてから調整することをオススメ**します。


### 変数を追加する

4つの変数を追加します。
![A04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/b2aa19f5-e012-5451-ccd1-cfb984d34640.png)
- 「Sound」: Sound Atom Cue型。再生するサウンドを指定します
- 「Volume」: float型。サウンドのボリュームを指定します
- 「Pitch」: float型。サウンドのピッチを指定します
- 「AutoActivate」: Bool型。サウンドが自動で再生開始されるかを判定します

すべて目玉のアイコンをクリックし、外部からアクセス可能にしておきます。


### 初期パラメータ用のConstruction Script

変数をAtom Componentのパラメータに反映するためのConstruction Scriptを用意します。
実装例は次のとおりです。
![A05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/0f9b540e-8f7a-262d-3c0f-cfd2f1838a19.png)

これでお手軽にサウンドを配置、設定できるアクターができました。
![A06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3ec85855-1f68-acf5-004a-f8b2aecb1462.png)


### 効率的な配置作業のために

こういったアクターの配置、初期パラメータの設定を効率的・視覚的にする方法について、過去の記事で解説しています（今回の実装には必須ではありません）。

**ADX+UEでサウンドの配置作業を効率化する**
https://qiita.com/SigRem/items/efd9a7b9aef44f463d73


## ボリューム内にあるサウンドを取得する

サウンドを雑多にレベル内に配置してみましょう。
![B01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/ee1fc2a5-b006-4555-1f4b-c9291fe46deb.png)
（白い球体がサウンド用のブループリントです）

範囲を設定するためのボリュームを配置します。
デフォルトで配置できる「Box Trigger」などを置くといいでしょう。
![B02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/606a6bbe-7498-2e46-c600-32af6e64e46f.png)
![B03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4003df64-3313-2ae7-9136-f5318f61428b.png)
スケールをそのままいじってもいいですが、取り回しをよくするためDetailsパネルの「Box Extent」でサイズを変更する方が良さそうです。
![B04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/0faa3c20-126d-f1f7-076b-7899a5b42ea2.png)

**Box Triggerを選択したまま**、レベルブループリントを開きます。
![B05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/560874da-a8c4-4a4f-bf90-2892b2cb6b51.png)

イベントグラフの空欄で右クリックし、「Create a Reference to （選択中のアクター名）」でリファレンスノードを作ります。
![B06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/d7923cd4-67a7-d814-ebb0-bd59e503b4ac.png)
![B07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/1fe4e834-1d8f-9add-9cb9-dfd5ebc03bab.png)
リファレンスノードから線を引き出し、**Get Overlapping Actors**ノードで特定のクラスのアクターだけを取得します。
「Class Filter」は今回作成したアクター名を指定します。
![B08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/f190eb83-c5a6-66a7-914f-3ad1251981b5.png)
**For Each Loop**ノードで取得したアクターごとに同じ処理をかけます。
**Print String**で取得したアクターの名前（**Get Object Name**）を出力します。
![B09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/fdaa4be8-24e9-894c-2af3-f66cb35a7606.png)
実行してキーを押すと、ボリューム内のサウンドがリストアップされていることが分かります。
![B10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/ceccbd21-deda-92f6-04f4-c22e93a8015d.png)


## 特定のボリュームに入ると、一定範囲内のサウンドのパラメータを変更する

ひとつの実装例として、「特定の地点まで進入すると、一定範囲内のサウンドが減衰する」演出を作ってみます。
レベル上にもうひとつのボリュームを配置します。
![C01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/1b0eb9a1-c06e-b145-9cb6-57add253822d.png)
このボリュームを選択した状態でレベルブループリントを開きます。
右クリックして「Add On Actor Begin Overlap」でボリューム進入時のイベントを作成します。
![C02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/7b7b6777-3a40-4080-f780-709e7c1014f2.png)
イベントを開始するノードが作られました。
![C03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/6f58ca14-933c-6376-0d81-573f3a3d0e70.png)

**Branch**ノードで進入したのがプレイヤーキャラかどうかを判別します。
![C04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/44134cc2-8359-ebfe-739e-af8eedf4ca7e.png)
Trueの場合、先ほどの処理のようにボリューム内のサウンドアクターを取得します。ノードはコピペでかまいません。
![C05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9dffa91d-8ab7-a91a-0e0f-e18b665f9ece.png)
アクター内のAtomコンポーネントにアクセスするために、**Cast**ノードをはさむ必要があります。
![C06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/c5e3072d-e252-14c7-f1be-4c6703be2b8b.png)
**Set Volume**でサウンドのボリュームを「0.1」に設定します。
![C07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/63cde61c-7d56-8d4d-dc8a-e2a65099f431.png)

これでテストしてみると、ふたつめのボリュームに入るとひとつめのボリューム内のサウンドのボリュームが一括で「0.1」となり、聞こえにくくなります。
![C08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/d6fbb432-6dd6-5aed-b0a8-802d563ce77c.png)

同じようにボリュームから退出した際のイベントも作れば、プレイヤーが元の位置に戻った際に聞こえてくるサウンドのボリュームも元に戻ります。
![C09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/fb2a1217-4b85-cafb-0dd6-1e45cb0bc7d6.png)


今回は単純にボリュームの変更でテストしましたが、Aisacコントロールやセレクタなどの細かいパラメータにも干渉することができます。
いちいちリファレンスノードを持ってくる必要がなく、参照漏れなどのバグを生みにくくなりますし、デザイナーが範囲を詳細に指定できることで意図通りの演出もしやすくなります。