はじめに
ADXアンバサダーとして記事を書いておりますSigと申します。
この記事ではアンリアルエンジン5とサウンドミドルウェア「ADX for UE」を連携させ、ゲームをプレイしながら裏でサウンド候補をA/B切り替えできるテストウィンドウを作ってみる実装を紹介します。
サウンド制作では「パターンAとBどっちがいい?」という問題を判断する場面が頻出しますが、静かな環境で単体再生すると良く聞こえる音も、実際のゲーム中のBGMや環境音と混ざると印象が変わることが多々あります。そのため、実プレイの文脈で鳴らしながら聞き比べたいところです。
テストウィンドウはUE5の標準機能である、Widget Blueprintで作成します。
実装概念としては応用が効きますので、キーでの切り替えなど様々な形式に変更することができます。
当記事ではUE5.7 及び 「ADX LE UE SDK(2.05.01)」を使用します。
また、基本的にブループリントのみでの実装を行います。
ADX for UEはインディー向けの「LE版」であれば、無料で使用できます。
前提
「ADX for UE LE」を使用します。導入や簡単な使い方は以下の記事にあります。
ADX for UEの導入で、一歩上のサウンド表現を(導入編)
ADX for UEの導入で、一歩上のサウンド表現を(実践編)
実装
仕組みの全体像
今回作るテストツールは、以下のように使用できます。
- ゲーム側: サウンド再生時に、直接キューを指定するのではなく「識別ID」をキーにして、GameInstanceに問い合わせて鳴らすキューを決定する
- Widget側: Play in Editor中のGameInstanceに対し、識別IDとキューの対応を書き換える
これにより、Play in Editorで実プレイしている最中にテストウィンドウでボタンを押すと、次のサウンド再生から切り替え後のキューが再生されます。
AtomCraftでサウンドを用意する
比較用のキューを用意します。今回はサンプルとして、攻撃や回避のサウンドについて2パターンを比較する想定でサウンドを用意しました。
- 「SE_Act_HitA」: 軽い斬撃音
- 「SE_Act_HitB」: 重い斬撃音
- 「SE_Act_DodgeA」: 軽く跳躍する音
- 「SE_Act_DodgeB」: 地面を滑り込むような音
マテリアルツリーにインポートし、それぞれのマテリアルからキューを作成します。

マテリアルをキューシートにドラッグ&ドロップすることで、自動的に「ポリフォニック」タイプのキューが作成できます。
複数のマテリアルを持っていくと、それぞれに対してひとつずつキューが作成されます。

今回はAtomCraftでの作業はこれだけです。
他にもA/Bテストしたいキューがあれば、すべて持っていきましょう。
ここまでできたらキューシートをビルドします。
UE5にサウンドを組み込む
UE5でビルドしたキューシートをインポートします。
acfファイルインポート時のダイアログでは両方とも「Yes」を選択します。
これにより、プロジェクトにAtom Configが自動的に設定されます。
acbファイル(キューシート)のアセットを開き、キューが正常に再生されることを確認します。

GameInstanceにサウンド差し替えマップを持たせる
GameInstanceは、ゲーム実行中に常駐し値を保持するクラスです。
本記事は既存のゲームプロジェクトに後付けする想定のため、すでにプロジェクトで使用しているGameInstanceに変数と関数を追加していきます。プロジェクト設定を開き、「Maps & Modes」→「Game Instance Class」で、現在使用中のGameInstanceクラスを確認できます。


新規プロジェクトでGameInstanceを作成する場合
まだプロジェクトにGameInstanceクラスを用意していない場合は、以下の手順で作成します。
コンテンツドロワーで右クリック→「Blueprint Class」を選択します。
親クラスは「GameInstance」を選択します。
「BP_GameInstance_ABTest」と名前をつけました。
プロジェクト設定でこのGameInstanceを使用する設定をする必要があります。
プロジェクト設定を開きます。
「Maps & Modes」の「Game Instance Class」に作成したGameInstanceを指定します。
GameInstanceをダブルクリックして開きます。
画像のような状態になっている場合、上部の「Open Full Blueprint Editor」をクリックするとブループリントエディタが開きます。

My Blueprintパネルで変数を追加します。
変数はMap型とします。
これは、自由な型をインデックスとして持てる変数です。
Map型変数を作るには、まずインデックスとして使用する型を選択します。
Detailsパネルにて、変数の型の右のプルダウンメニューで「Map」を選択します。

インデックスを「Key」、値を「Value」と呼びます。
KeyがName、ValueがAtom Sound Cueの変数を作成します。

「SoundMap」と名前をつけました。コンパイルをしておきます。

識別IDとキューのペアをあらかじめ登録しておきます。
Key「Hit_Normal」→ Value「SE_Act_HitA」です。

識別ID経由でサウンドを再生する共通関数を作る
GameInstance内に関数を作成します。
引数としてName型の「SoundId」を受け取るようにします。
Inputsの引数を追加します。

関数内では、SoundMap変数のFindノードで該当IDのキューを取得します。
FindはKeyを指定して要素を探し、Valueを返すノードです。

取得できた場合はSpawn Sound 2Dでそのキューを再生します。
必ずAtomカテゴリのものを使用します。
該当IDがない場合にはデバッグメッセージをPrint Stringで表示しておくと分かりやすいです。

ゲーム側のサウンド再生処理をID経由に書き換える
従来では直接キューを指定してSpawn Sound 2DやPlay Sound at Locationで再生していた処理を、GameInstance経由の呼び出しに書き換えます。
例えばプレイヤーの攻撃アクションで、従来では次の画像のようにキューを直接指定して再生していたとします。
これを、GameInstanceを経由したテストサウンドの再生に切り替えます。
Get Game Instance→Cast to (プロジェクトで使用するGameInstanceクラス)→PlaySoundById("Hit_Normal") に書き換えます。
一度書き換えてしまえば、以降はGameInstanceのSoundMapを書き換えるだけでサウンドが差し替えられるようになります。
以前のサウンド再生ノードは退避させて、テストが完了したらまた繋ぎ直しましょう。
テストウィンドウを作る
コンテンツドロワーで右クリック→「User Interface」→「Widget Blueprint」でWidget Blueprintを新規作成します。

親クラスには「User Widget」を選択します。
「WBP_SoundABTester」と名前をつけました。
ダブルクリックして開き、Canvas Panelを配置します。

簡単な表示と2つのボタンを配置します。テスト候補によってはボタンが増えたり、プルダウンメニューにしてもOKです。

ボタンを選択し、Detailsパネルで「On Released」のイベントを追加します。

Get Game Instance→Cast To (プロジェクトで使用するGameInstanceクラス)をつなげてキャストします。

Map型の変数にAddノードを使用し、値を書き換えます。
Addノードは値を追加しますが、既存のKeyに対して使用するとValueを上書きします。

インプットピンを右クリックし、「Promote to Variable」で変数化します。

もう片方のボタンに対しても同じ処理を行います。

ノードの全体図はこんな感じです。

それぞれの変数化したキューに対し、切り替えたいサウンドをDefault Valueで指定します。

実際に使ってみる
キー入力の効くアクターに、テストウィンドウを表示する機能を追加します。
キー入力を検知します。

Create Widgetノード、Add to Viewportを使ってウィンドウを表示します。
また、UI操作のためにGet Player Controller→Show Mouse Cursorでマウスカーソルを有効化する必要があります。

Flip Flopノードを挟み、ボタンを押すたびにUIを消してマウスカーソルの表示もオフにする処理を入れます。

Play in Editorを開始し、プレイ中にテストウィンドウのボタンを押すと、次の攻撃から音が切り替わることが確認できます。

これでゲームを実行したままサウンドを切り替え、A/Bテストできるようになりました。
識別ID経由で再生する設計は、A/Bテスト以外にもキャラクターごとの効果音差し替えや場面に応じた汎用的な効果音の再生にも応用が可能です。
























