はじめに
UE4.23+「ADX2 LE v2.10.05」を使用します。
アンリアルエンジン4とサウンドミドルウェア「ADX2 for UE4」を連携させ、
ゲーム内の雨の環境音の挙動を実装します。
基本的な実装については前回の記事を参照してください。
UE4+ADX2で作る、軒下での雨音表現(基本編)
https://qiita.com/SigRem/items/7a534e5f2fa4109015dc
今回の実装例
基本編では建物に入った際に雨がフェードアウトするだけでしたが、今回は建物に雨が当たる音の表現も加えてみます。
また、トリガーで建物への進入を判定していましたが、頭上に天井があれば自動的に雨音に変化を加えるようにします。
前提
「ADX2 for UE4 LE」を使用します。導入や簡単な使い方は以下の記事にあります。
ADX2 for UE4の導入で、一歩上のサウンド表現を(導入編)
https://qiita.com/SigRem/items/4250925f6d66a4fd287a
ADX2 for UE4の導入で、一歩上のサウンド表現を(実践編)
https://qiita.com/SigRem/items/c089b71c42e898980a46
やること
- AtomCraftでキューに雨のバリエーションを追加
- Aisacコントロールを使用し、エフェクトを追加
- UE4にインポート
- ブループリントでプレイヤーの挙動を監視、必要に応じて雨の音にエフェクトをかける
実装
AtomCraft側
キューの作成
新規にキューを作成します。
通常の雨の音の他に、建物の近くで聞く雨の音の素材をインポートしておきます。
ふたつの素材をキューにドラッグアンドドロップして、ふたつのトラックを作ります。
リネームし、通常の雨の音を「Track_Rain_Outside」、建物の中から聞く雨の音を「Track_Rain_Inside」としています。
AISACの設定
ふたつのトラックについて、それぞれボリュームとハイパスフィルタのAISACコントロールを作成します。
合計4つのグラフを作ることになりますが、AisacControlはボリュームとハイパスフィルタの2つぶんになります。これにより、「トラックAが減衰するとトラックBがフェードインする」といったように、ふたつのトラックのボリュームとフィルタの数値を連動させることができます。
トラックを選択して「新規オブジェクト」→「AISACの作成」をします。
「Track_Rain_Outside」には「Aisac_VolumeA」「Aisac_HighPassA」のふたつを作成します。
「Track_Rain_Inside」には「Aisac_VolumeB」「Aisac_HighPassB」のふたつを作成します。
AISACコントロールのIDを間違えないようにしましょう。ボリュームは「AisacControl_00」、フィルタは「AisacControl_01」です。
雨音の自然な移り変わりを実現するためのグラフを考えてみましょう。
上の画像のように、左側では建物の外で聞く音に、右に行くほど屋内で聞く音に近づくようにします。
4本のグラフを編集します。
テスト再生しながらAISACコントロールを動かしてみると調整しやすいです。特に中間の音は聞きながら微調整しましょう。
例として次のようなものができました。
▼Track_Rain_Outsideのボリュームは屋内に入ると、中間ほどから急激に減衰します。
▼Track_Rain_Outsideのハイパスフィルタも同様に減衰していきます。
▼Track_Rain_Insideのボリュームが代わりに増加しますが、屋内から聞こえる雨なので右端でも音量を抑えておきます。
▼Track_Rain_Insideのハイパスフィルタも同様です。
聞き返してみて問題なければ、キューシートをビルドします。
UE4側
キューシートのインポート
エクスポートしたキューシートをインポートします。
新しく作ったAtom Cueをレベルに配置します。
イベントグラフを開き、基本編で配置したノードの中からAtom Cueの参照ノードを新しいものに置き換えます。
タイムラインノードをダブルクリックして開き、グラフを以下のように変えます。
屋内に入ると段々とAISACコントロールグラフの右側へと遷移していくイメージです。
テストしてみましょう。より自然なフェードに聞こえると思います。
Tips
頭上に障害物がある場合に雨音をフェードさせる
これまでの実装ではトリガーで特定の場所だけ屋内の判定を作っていましたが、トレースを使ってプレイヤーの頭上が遮られたら屋内判定にする手法も紹介します。
▼プレイヤーの頭部座標から上方に判定を飛ばし、何か遮るものがないか自動的に判別します。
▼もし遮られたら、屋内に入ったものとして雨音のフェード処理を行います。
ブループリントのグラフは以下のようになります。
▲Event Tickから処理を開始します。毎フレーム行われるイベントです。
▲Get Player Characterでプレイヤーキャラであるアクターを取得します。また、Get Actor Locationでアクターの座標を取得します。
▲vector + vectorノードをふたつ作り、それぞれトレースの開始地点である「アクター座標にZ100を加えたもの」(キャラクターの頭上座標)とトレースの目標地点である「アクター座標にZ10000を加えたもの」(高度約10000)の数値を入力します。
▲LineTraceByChannelノードに必要な線をつなぎ、トレース処理が完成します。
LineTraceByChannelの後にBranchノードを配置し、LineTraceByChannelの「Return Value」を「Condition」につなげます。
▲トレースに遮蔽物があれば、LineTraceByChannelの「Return Value」はTrueを返します。
▲後は今までに作ったタイムライン以下のノードをコピペすればOKです。
デバッグ用にLineTraceByChannelノードの「Draw Debug Type」は「For One Frame」に設定しておきましょう。これにより、毎フレームトレースのラインが描画され動作を確認しやすくなります。
実行してみましょう。キャラクターの頭上に線が描画されます。
これが遮られると、雨音の処理が行われるはずです。
カメラを基準にしてトレースを使う
前項ではキャラクター基準のトレースを行いましたが、TPSではカメラの位置から判定をとったほうが自然な印象になることもあります。
カメラ位置からのトレースには、次のような処理が必要です。
▲Event BeginPlayノードでゲーム開始時に実行されるイベントを作ります。
▲Get PlayerCharacterでプレイヤーキャラのアクターを取得し、Cast To (プレイヤーキャラのアクター名)でアクターのクラスにキャストします。これはキャラクターが持つカメラにアクセスするための処理です。
▲Cast To (プレイヤーキャラのアクター名)ノードの青いアウトプットピンを右クリックし、「Promote to Variable」でアクタークラスの変数を作成します。
▲「MyChar」といったように分かりやすい名前をつけます。
▲先ほどのトレース処理に戻り、Get MyCharからGet Follow Cameraでカメラのリファレンスノードを取得し、GetWorldLocationノードでカメラの座標を取ります(カメラはアクターではなくコンポーネントのため、Get Actor Locationが使えません)。
あとは同じ用にvector + vectorノードでつないで完成です。