0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ADX+UEで、デバイスの入力強度に応じてサウンドを変化させる

Last updated at Posted at 2022-10-11

はじめに

アンリアルエンジン4とサウンドミドルウェア「ADX2 for UE4」を使って、ゲームパッドなどのデバイスの入力した強さにより、サウンドを変化させる実装です。
「トリガーを引く強さによって銃の発射精度が変わり、弾の発射音も影響される」
「スティックを弾いた強さに応じて音の重さが変わる」
などといった、プレイヤーの入力に対するフィードバック手段として有効です。

実装にはADX for UEの機能「AISACコントロール」を使用します。

前提

当記事では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を起動し、プロジェクトを用意したら効果音となるマテリアルをインポートします。
A01.png
今回は
「トリガー入力の押し込みで音が高くなる機関銃」
「スティック入力の強さで音が二段階に変化するジャンプ音」
を想定し、機関銃のサウンド1種とジャンプのサウンド2種(弱ジャンプ、強ジャンプ)を用意しました。

キューの作成

マテリアルを再生するためのキューを作成します。
ワークユニットツリーでキューシートを右クリックし、「新規オブジェクト」→「キュー『ポリフォニック』の作成」を選択。
A02.png
マシンガン用のキューとジャンプ用のキューを作成し、それぞれに用意したマテリアルをドラッグアンドドロップして配置します。
A03.png
A04.png
マテリアルがループ用の素材になっていれば問題ありませんが、今回用意したマシンガン用サウンドはループしてほしいにも関わらず、ワンショット用のものなのでループ用のマーカーを加えます。
タイムライン上の空欄を右クリックし、「新規オブジェクト」→「マーカーの作成」を選択します。
A05.png
タイプは「シーケンスループ」で「追加」をクリックします。
A06.png
テスト再生して確認しながら、ループマーカーを適切な位置に持っていきます。
A07.png
これでふたつのキューが用意できました。

AISACコントロールの設定(ピッチ)

トリガー入力などに応じて音を変化させるために、AISACコントロールを設定します。
マシンガン用のキューを選択し、トラックリストの空欄を右クリックして「新規オブジェクト」→「AISACの作成」を選択。
A08.png
マシンガンのサウンドは入力によって音の高さを変えたいので、AISACグラフタイプは「ピッチ」とします。
A09.png
AISACリストでピッチを選択し、グラフを編集します。
A10.png
0に近づくほど少しだけ値が下がっている直線のグラフとしました。
テスト再生中に上部のスライダーを動かすと、音の変化がプレビュー可能です。
ボタン入力をイメージしながら、操作していて気持ちよさそうな塩梅を探してみましょう。
A11.png
編集しおえたら、タブを切り替えてタイムラインに戻ります。
A12.png

AISACコントロールの設定(ボリューム)

今度はジャンプ用のキューにAISACを設定します。
ジャンプ用のキューを選択します。
トラックリストの弱ジャンプ用トラックを右クリックして「新規オブジェクト」→「AISACの作成」を選択。
A13.png
今度はグラフタイプを「ボリューム」とします。
A14.png
すぐにタイムラインに戻り、強ジャンプ用のトラックについてもAISACを作成します。
A15.png
まったく同じ設定で追加します。ここで同じAISACコントロールを使い回すことにより、ひとつの値でふたつのトラックのボリュームを相互に入れ替えることが可能です。
A16.png
ふたつのトラックの数値が真逆になるよう設定します。右側の「ポイントリスト」を使うと詳細な数値が入力できて、設定しやすいかもしれません。
A17.png
画像のような形のグラフができたら、テスト再生して動作を確認します。
A18.png

キューシートのビルド

AISACコントロールが完成したら、UEに持っていくためにキューシートをビルドします。
A19.png
A20.png

UEでの実装

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

ここからUEに移ります。
ビルドしたacbファイル、acfファイルをコンテンツブラウザへとドラッグアンドドロップして配置します。
B01.png
B02.png
プロジェクト設定を開き、
B03.png
CriWareタブの「Atom Config」に今回出力したacfファイルを設定します。
B04.png
ここで一度エディタを再起動しておくことをおすすめします。

入力の強度を取得する

入力を取得するため、キー(ボタン)を登録します。
ふたたびプロジェクト設定を開きます。
B05.png
キー入力の設定は「Input」タブで行います。
B06.png
ボタンを押した/離したといった判定は「Action Mappings」で行い、スティックやトリガーを入力した強度といった判定は「Axis Mappings」で行います。
「Axis Mappings」を追加します。
B07.png
「Fire」という名前で、ゲームパッドの右側トリガーの入力を登録しました。
B08.png
ジャンプアクションに関しては、今回はスティックのX軸とY軸入力を合計する形で判定します。
両方の入力を登録しましょう。
B09.png
※既にキャラクターの移動などの動作にスティックを使用している場合、干渉することがあります。どちらかを別の入力にしてもいいでしょう。

入力をテストする

登録したインプットが正常に測れるか、テストしてみましょう。
レベルブループリントを開きます。
B10.png
Print Stringノードで毎フレームのトリガー入力強度を表示します。**Get Fire(登録した入力名)**で登録したトリガーを押した強さを受け取れます。
B11.png
Get Fireノードのプロパティには「Consume Input」という項目があります。これにチェックが入っていると、別の場所からの入力処理を受け付けなくなります。後にキャラクターに処理を追加した際に動かなくなることが想定されますので、チェックは外しておきましょう
B11b.png
ゲームを再生しゲームパッドのトリガーを入力すると、押した強さが表示されるようになりました。
B12.png

同じようにスティック入力も計測してみます。
「StepX」「StepY」の入力をとり、absノードを噛ませます。これは受け取った値を「絶対値」に変換するものです。スティック入力は逆方向に倒すことでマイナスの値になるため、入力強度を知りたい場合はこのノードで正の値にすると分かりやすいです。
B13.png
合計した値は入力方向によっては1を超えることがありますので、clampノードで最大値を設定して丸めます。
B14.png
これでトリガーとスティックの入力がそれぞれ表示されるようになりました。

強度に応じてサウンドを変化させる(機関銃)

キャラクターのブループリントに入力処理を追加します。

処理が長くなるためこの記事ではマクロ化していますが、そのまま記述しても動きます。
マクロはMy Blueprintパネルから追加できます。
E01.png
作成したマクロを選択し、DetailsパネルでInputsとOutputsを追加します。
「Value」には入力強度の数値を渡します。
また、アクションが成功したかどうかで処理を分岐させたいため、Outputsには「true」「false」のふたつの出口を用意します。
E02.png

発射処理用の変数を追加します。
Vector型の「FireLoc」、float型の「FireCount」「FireRate」です。
「FireRate」は弾の発射間隔の最速値です。今回は「0.1」としました。トリガーの最大押し込みにより、0.1秒間隔の発射となります。
C01.png
まずは入力強度の数値を受け取り、発射処理を開始すべきか判定します。
ここで分岐させないと、数値を受け取っただけで発射判定になってしまうため常に機関銃を撃ち続けることになってしまいます(数値が0でも処理は行われる)。
今回は入力強度が「0.1」以上で処理に移ることにしました。
C02.png
もし機関銃のサウンドが停止されている場合、Atomコンポーネントの再生を行います。再生状態の取得はGet Statusノードで行えます。
C03.png
変数「FireCount」を減算し、0以下になれば弾をスポーンさせます。押し込みの強さをDelta Timeにかけ、押し込みが強いほど減算を速くし、弾の発射間隔も狭まるようにします。
C04.png
「FireCount」に「FireRate」を代入し、発射間隔をリセットします。Spawn Actorで弾アクターをスポーンさせます。
「FireLoc」は弾の発射位置(スポーン位置)となります。
OutPutsノードへと線をつなぎ、マクロ外へと処理を続けます。
C05.png
入力強度が0.1未満だった場合、機関銃のサウンドを停止します。
C06.png
停止後、Outputsへと処理を続けます。
C07.png
マクロ内の処理の全体図です。
C08.png

入力処理に戻り、Set Aisac by Nameノードで「Axis Value」を渡してあげればサウンドが変化します。
B15.png

強度に応じてサウンドを変化させる(ジャンプ)

ステップジャンプに関しては先ほどのテストと同様、合計して値を丸めておきます。
B16.png

マクロ内グラフを書いていきます。
入力強度が0.2以上であればステップジャンプ処理を開始します。
D01.png
アクションの条件として、キャラクターが地上にいる状態かを判定します。
キャラクタークラスであれば、Character Movementコンポーネントから線を引き出しIs Fallingノードでキャラクターが落下中(空中にいる)か取得できます。地上にいる状態をTrueとしたいので、NOTノードを噛ませてBranchノードの条件式とします。
D02.png
TrueであればLaunch Characterノードでキャラクターをジャンプさせます。
D03.png
ジャンプするベクター(方向と強さ)を算出するには、次の画像のように計算します。
キャラクターの回転を取得し、前方ベクター×ステップ基礎速度×入力強度+ジャンプする高さです。
実装例ではステップ基礎速は「4000」としてあります。
D04.png
ステップ実行後、Outputsノードの「True」へとつなぎます。
D05.png
入力強度不足、またはキャラクターが空中にいるなどでステップジャンプが成功しなかった場合は、Falseへとつなぎます。
D06.png

マクロから出て、イベントグラフへ戻ります。
Spawn Atom Sound LocationでAtom Cueをスポーンさせて再生します。「Auto Destory」(再生終了時にコンポーネントをデストロイする)にはチェックを入れておきましょう。
B17.png
最後にスポーンしたサウンドに対して、Set Aisac by Nameでサウンドを変化させてあげましょう。
B18.png

プレイヤーの入力に対してサウンドで応えてあげることで、操作がしっかりと伝わっている実感やプレイングの気持ちよさにもつながります。
細かい演出ですが、プレイ中何度も使うアクションだからこそ凝ってみたいところですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?