はじめに
アンリアルエンジンとサウンドミドルウェア「ADX for UE」を連携させ、「ゲーム中に登場しているNPCに応じて街の環境音を動的に変化させる」実装を行ってみます。
たとえばゲーム内の街のマップや拠点において、NPCの数が多いほど街の喧騒音を大きくさせ、また鍛冶屋や商人がいる場合のみ専用の環境音を再生します。
「鍛冶屋がいれば金槌の音が聞こえ、商人がいれば商品をアピールしている声が聞こえる」といったように、よりいきいきとした環境音表現ができる効果が期待できます。
注意点として、あくまで環境音としての実装のため、厳密に3D空間上に音を配置したい場合は該当部分のみアプローチを変える方法があるかもしれません。
例:街と群衆の喧騒のみこの記事の方法で実装させ、鍛冶屋や商人から発する音はアクターに紐づける形で配置する、等
前提
当記事ではUE5.0を使用しています。基本的にブループリントのみでの実装を想定します。
ADXはインディー向けの「LE版」であれば、無料で使用できます。
https://game.criware.jp/products/adx-le/
なお、ADX2は「ADX」へ名称が変更になりましたが、ツール構成は変更ありません(2がないから古いほう、というわけではありません)。
記事執筆時点のADX for UEのSDKバージョンはADX LE UE SDK(1.31.00.01)です。
ADX for UEの導入や基本的な使い方は以下の記事にあります。必要に応じて参照してください。
ADX for UEの導入で、一歩上のサウンド表現を(導入編)
ADX for UEの導入で、一歩上のサウンド表現を(実践編)
実装
AtomCraftで環境音を構成する
マテリアルの用意
まずは環境音の素材となるマテリアルを用意します。
今回用意したのは以下の4種です。
- 基本の環境音となる「BGS_Town」
- 鍛冶屋がいる場合に再生される「BGS_Town_Blacksmith」
- 商人がいる場合に再生される「BGS_Town_Merchant」
- キャラクター数に応じて音量が変化する、喧騒の環境音「BGS_Town_Crowd」
各効果音はインスペクターにて、ループするよう設定しておきましょう。
キューの作成
街の環境音となるキューを作成します。統合された環境音としたいので、今回作成するキューはこの一つだけです。
ワークユニットツリーのキューシートを右クリックし、「新規オブジェクト」→「キュー『ポリフォニック』の作成」を選びます。
作成したキューに、すべての環境音をトラック別に挿入します。
Aisacコントロールの作成
トラック「Track_BGS_Town_Blacksmith」を右クリックし、「新規オブジェクト」→「AISACの作成」を選択してAisacコントロールを作ります。
分かりやすいよう名前をつけますが、UE側では中段にある「AisacControl_00」の名前を使用します。
グラフタイプは「ボリューム」です。
AISACリストから「ボリューム」を選択し、グラフを編集します。
右肩上がりの単純なグラフにします。
右枠の「ポイントリスト」から数値を入力してもOKです。
編集できたらスライダーを動かし音量の変化をチェックしてみましょう。
チェックの際は、一時的に他トラックの音量を下げると分かりやすいかもしれません。
同じように、商人用の環境音、喧騒用の環境音に対してもAisacコントロールを作成します。それぞれIDが異なるよう選択してください。
すべてのトラックに対し、それぞれのAisacコントロールのグラフを同じように編集します。
画像では重なっているため一本のグラフに見えますが、実際は3本の線があります。
キューシートのビルド
ここまでできたら、キューシートをビルドしてUEに持っていきます。
UEで環境音を変化させる
キューシートのインポート
UE側のコンテンツブラウザに、ビルドしたacfファイル、acbファイルをドラッグ&ドロップしてインポートします。
プロジェクト設定を開き、「Atom Config」に今回ビルドしたacfファイルを指定します。
サウンドの配置
レベル上にサウンドを配置します。
Detailsパネルにて、Aisacコントロールの初期値が設定できます。初期値をすべて「0」にしておきましょう。
「AisacControl_00」~「AisacControl_02」の値を「0.0」にします。
この状態でゲームを再生すると、プレーンな状態の街の環境音だけが聞こえるはずです。
アクターを検知して鍛冶屋、商人の音を追加する
ブループリントを使用し、検知したアクターに応じて環境音を追加する処理を書いていきます。
検知対象となるアクターを作成します。もし既に目的のアクターを作ってある場合は省いて大丈夫です。
「鍛冶屋」や「商人」は大体の場合、親クラスは「Character」で作るかと思います(それ意外のクラスで作っていても大丈夫です)。
鍛冶屋のアクターが作成できました。
ダブルクリックして開きます。
見た目が設定されていませんので、仮でメッシュを指定します。
アニメーションブループリントなども設定しておくと、Idleアニメーションが再生されていい感じかもしれません。
レベルブループリントを開きます。環境音再生用のアクターを作成しても大丈夫です。
右クリックして、「Add Custom Event」でカスタムイベントを追加します。
今回は「CheckTownSound」と名付けました。これは街の音を変化させるトリガーになります。
街の状態が変わったり、プレイヤーが街のマップに出入りした際に実行するといいでしょう。
今回はテスト用として、仮で「1」キーを押してイベントを呼び出すようにしてみます。
イベントが開始されたら、Get All Actors Of Classノードでレベル上のアクターを取得します。
まずは「Actor Class」に鍛冶屋となるアクタークラスを指定します。
このノードには「Out Actors」というアウトプットピンがあります。Array(配列)として検知したすべてのアクターのリストが取得できますので、Lengthノードでリストの長さを測ればアクター数が判明する、というわけです。
試しにPrint Stringノードを使い、アクター数を文字として出力してみましょう。
レベル上に配置しているアクター数により、画面に出力される数字が変わるはずです。
正常に動いていることが分かったら、キューに対してAisacコントロールをかけていきます。
レベル上でキューを選択しておき、レベルブループリントに戻ります。
右クリックし、キューのリファレンスノードを配置します。
リファレンスノードから、AIsacコントロールを行うためのノードSet Aisac by Nameを作成します。
Selectノードを使い、「鍛冶屋がいればAisacコントロールの値を1に、いなければ0に」します。
これで鍛冶屋の検知をし、いれば専用の環境音を鳴らす処理ができました。
同じように商人用のアクターも用意し、処理を組んでみましょう。
Characterクラスを継承したアクター「BP_Char_Merchant」を作成しました。
レベルブループリントに戻ります。
Sequenceノードでグラフを整理しましょう。
鍛冶屋用のノードをコピペし、検知するクラスとAisacコントロール名を変更すれば完成です。
この状態でコンパイルすると、参照クラスを変えたためにエラーが出ることがあります。
その場合はLengthノードを作り直し、コンパイルすることでエラーが解消されます。
キャラクター数に応じて喧騒の音量を変化させる
キャラクター数を自動で数え、その数に応じて喧騒の音を大きくしてみましょう。
Sequenceノードの「Add pin」ボタンを押し、ピンを追加します。
鍛冶屋「BP_Char_Blacksmith」と商人「BP_Char_Merchant」は「Character」クラスを継承している子アクターですので、「Character」クラスの数を取得すると子クラスとして一緒にカウントされます。
Get All Actors Of Classノードを使用し、レベル上に存在する「Character」クラスのアクター数を数えてみましょう。
Map Range Clampedノードで、取得したアクター数をAisacコントロールの値としてスケーリングして渡します。
キャラクターが10人以上で喧騒のボリュームが最大化するようにします。
キャラクターを増やして「1」キーを押すとキャラクター数がカウントされ、喧騒の音量が変化するようになりました。
さらにキャラクター数が増えた場合に、さらに賑やかな環境音を追加するなどの処理を追加すれば、より発展している街や拠点といった雰囲気も出せそうです。
プロジェクトの形態に応じて取り入れて、よりゲームの状態が反映された環境音を再生してみるのも面白いかもしれません。