はじめに
ADXアンバサダーとして記事を書いておりますSigと申します。
この記事ではUE5とADX for UEを連携させ、マルチプレイヤーゲームにおける、次のようなシチュエーションについて実装を行います。
- マルチプレイヤーゲーム内でプレイヤーがボタンを入力すると、対応したボイスが再生される
- ボイスは数種類の中からランダムで再生
- ランダムなボイスは、すべてのプレイヤーに同期されて再生される
普通に「ボイス再生時にランダムなボイスを再生する」処理では、プレイヤー(クライアント)ごとに異なるボイスが再生されてしまいます(こちらは下記で検証します)。同じタイミングで遊ぶプレイヤー間の体験を統一するため、ランダムにピックアップされるサウンドも同期する処理を作ってみましょう。
やること
- ADX for UEを使ってサウンドを再生する
- マルチプレイヤーのテストプレイを有効にする
- 参加しているプレイヤー全員にサウンドを再生する
また、記事中に「blueprintue」を使用したBPグラフ共有を載せています。コピペするだけで大体の実装ができますので、よろしければご活用ください。
当記事ではUE5.6 及び 「ADX LE UE SDK(2.04.02)」を使用します。
また、基本的にブループリントのみでの実装を行います。
ADX for UEはインディー向けの「LE版」であれば、無料で使用できます。
https://game.criware.jp/products/adx-le/
前提
「ADX for UE LE」を使用します。導入や簡単な使い方は以下の記事にあります。
ADX for UEの導入で、一歩上のサウンド表現を(導入編)
ADX for UEの導入で、一歩上のサウンド表現を(実践編)
実装
AtomCraftでサウンドを構成する
マテリアルを用意する
ボイスのバリエーションとなるサウンドを今回は3つ用意しました。マテリアルとしてインポートします。
整理しやすいよう、マテリアルツリー内の「CharacterVoice」フォルダに格納しました。

キューを作成する
キューを新規に作ります。
キューシートを右クリックし、「新規オブジェクト」→「キュー『スイッチ』の作成」です。

名前をつけます。

マテリアルツリーからキャラクターボイスのバリエーションをすべて選択し、キューにドラッグ&ドロップして配置します。

キュー内に、トラックが分かれて配置されました。

ゲーム変数を設定する
これらのバリエーションを再生し分けるために「ゲーム変数」機能を使用します。
プロジェクトツリーの「ゲーム変数」を右クリックし、「新規オブジェクト」→「ゲーム変数の作成」を選択します。

新しいゲーム変数に「RandomVoice」を作りました。

キューを選択し、インスペクターにて「スイッチ」をクリックします。
参照するゲーム変数から、先ほど作った「RandomVoice」を指定します。

「等分化」ボタンを押し、スイッチ幅を等分に揃えます。
この場合、0.333...刻みでボイスのバリエーションが切り替わります。

ゲーム変数を選択し、初期値を変更して再生ボタンを押して、ボイスのバリエーションが変化することを確認します。

キューシートをビルドする
ここまでできたらキューシートをビルドします。

ビルド対象のキューシートすべてにチェックをつけ、ビルドします。

UEでサウンドを実装する
キューシートをインポートする
ビルドしたacbファイル、acfファイルをコンテンツドロワーにドラッグ&ドロップして配置します。
キューシートが複数ある場合はacbファイルもその数だけ出力されるので、すべてインポートしましょう。

キューシートアセットを開き、キューが正常に再生されることを確認します。

マルチプレイ対応のボイスを再生する
ひとまず、サーバーとクライアント間で同じキューが再生される処理を作ります。
プレイヤーキャラクターなど、ボイスを再生する主体のブループリントアクターを開き、イベントグラフに移動します。
ボイスマネージャーなどのサウンドを管理するアクターがある場合、そちらを使用します。
再生するアクターはRPCが飛ばせるよう、プロパティで「Replicates」にチェックがついている必要があります。

カスタムイベントに名前をつけます。イベント名の最初に「Multicast_」とつけるか、イベントノードを選択してDetailsパネルでReplicatesを「Multicast」にします。
これはすべてのプレイヤーに対して送信されるRPCになります。

Spawn Sound 2Dノードで減衰のないボイスを再生します。
必ずAtomカテゴリのものを使用します。AudioカテゴリのものはUE本来のサウンド用のものですので、Atomキューの再生には使用できません。

ノードが作られました。

再生するサウンドはカスタムイベントの引数とし、外部から再生するキューを指定できるようにします。

Multicastのイベントを呼べるよう、新たにカスタムイベントを作成します。
こちらは「Server_」と頭につけるか、Detailsパネルの「Replicates」から「Run on Server」を指定します。

Server側のカスタムイベントから、Multicastのイベントを呼び出します。

キーを押したらServer側のイベントを呼び出します。

呼び出す際、再生するキューシートとキューを指定します。

これでひとまず、固定のボイスが同期され再生されるようになりました。
ランダムなボイスを再生する&同期検証
次は再生するボイスをランダムなものにしてみましょう。
キューの再生時にゲーム変数を指定し、値に応じて異なるトラックを再生します。
Set Game Variable Value by Nameノードを使用します。

ノードのValueに、Random Float in Rangeを使って出力したランダムな数値を渡します。

これでランダムなボイスが再生されるわけですが、果たしてサーバー側とクライアント側すべてで同じボイスが再生されるのでしょうか?
検証してみましょう。
Random Float in Rangeノードの出力結果を「Promote to Variable」で変数化します。

変数化した値をSet Game Variable Value by Nameノードに渡すよう繋げます。

ランダムで出力された結果をPrint Stringノードで可視化します。

ゲームを再生してみましょう。
ボイスを3度再生した結果が次の画像になります。
サーバー側とクライアント側でそれぞれ異なる数値が出力されています。
ゲーム変数に従って異なるトラックが再生されているので、つまりボイスは同じものが再生されているとは限らない、ということになります。

ランダムな要素を同期する
では、ランダムな要素を動悸するにはどうしたら良いのでしょうか?
RPCに直接情報を渡せば、それはすべてのクライアントに伝播します。つまり、カスタムイベントに引数を渡してあげれば良いのです。
Random Float in Rangeノードを削除します。

Set Current Random Valueの値はカスタムイベントから渡せるよう繋げます。

Server_PlayRandomVoiceからMulticast_PlayRandomVoiceへと値が渡るよう繋げます。

Server_PlayRandomVoiceの呼び出し時に、こちらでRandom Float in Rangeノードを使いランダムな値を渡します。

ここまでのブループリントはこちらから取得できます。
これでテストしてみましょう。
結果は次のとおり。実行ごとのランダムな値は、見事に統一されているようです。
これでランダムなボイスも同じものが再生されるようになりました!

