ゲームにインタラクティブミュージックを実装しよう
ゲームを遊んでいるとき、ゲームの展開に合わせて音色が変化するBGMについて気が付いたことがありますか?
通常、ゲームのBGMとは3分や5分など決まった時間の素材をループすることで実現します。曲の「イントロ」と「ループ部分」を分けたデータにしておき、曲の鳴り始めだけにイントロを再生する手法もよく使われますが、そちらの解説は次回にて。
さて、ゲームにおける「インタラクティブミュージック」はゲームプレイの内容に応じて鳴っている曲をリアルタイムに変化させる手法をさします。
ボスの体力が減ってきたときに派手な楽器の音を加える、自身の体力が少なくなってきたときに不穏な音を加える、プレイヤーキャラがマップを移動したときに土地柄に合わせた楽器を入れる...など、ゲーム内のトリガーにあわせて曲を変化させます。ステージの終盤で曲が早回しになるのも一種のインタラクティブミュージックですね。
(細かくは、ユーザーの入力によって直接的に変わるものをインタラクティブミュージック、ステージ変化などのゲーム側の演出で変わっていくものをアダプティブミュージックと呼んだりもします。)
どのようなものを「インタラクティブミュージック」と呼ぶかは諸説ありますが、ここでは「ゲーム内容の状況に合わせて変化する楽曲」とします。
事例ですと、「オクトパストラベラー」がインタラクティブミュージックを積極的に取り入れていました。
本作はRPGです。特定のボス戦時のみ、フィールドマップから戦闘シーンに移るシーンで楽曲がシームレスに変化します。
http://jp.gamesindustry.biz/article/1810/18101501/
ゲームの進行と連動した音楽の演出はプレイの盛り上がりや焦りを与えることができ、うまくつかえば最高に「アガる」演出になります。
では、Unityを使った自作ゲームでこうしたインタラクティブミュージックを導入するにはどうしたらいいでしょう?
ADXについて
インタラクティブミュージックはUnity 標準のオーディオ機能でもできます。しかし後述しますが高度なサウンド知識と制御コードの実装が要求されるため、本記事は、サウンドの知識があまりないプログラマーでも実装できるよう、サウンドミドルウェアの「CRI ADX」の無料版を使います。
統合型サウンドミドルウェアCRI ADX
https://game.criware.jp/products/adx/
無償版サウンドミドルウェアADX LE
https://game.criware.jp/products/adx-le/
理由は次の通りです。
- Unity標準システムだと厳密なタイミング制御が難しい
音をサンプル単位で管理する必要があるのですが、Unity標準機能では難しいです。
もちろん自前でやろうとすると制御用のコードを大量に書く必要があります。 - マルチトラック(複数音の同時再生)を行うとCPU負荷が高い
Unityの標準機能や、その他のサウンドツールでは圧縮コーデックにOgg Vorbisを使っています。大量に音を鳴らす場合でさらにマルチトラックの再生となるとCPU負荷が高くなってしまいます。
「ADX」にはゲーム専用のコーデックとして「HCA」「HCA-MX」を搭載していますので、CPU負荷を気にしなければいけない場面では有利です。(特にモバイル端末、Android端末では実績が多いです。)
本エントリーでは、ADXをUnityに導入する手順や用語について詳しくは述べていません。はじめてADX / ADX LEを触る方は、前章の「Unityのサウンド機能をADXで強化する」をご確認ください。
(ちなみに2021年に「ADX2」から「ADX」にブランドが変わりました。製品構成は一緒です)。
開発中ゲーム「デモリッション ロボッツ K.K.」デモ版のインタラクティブミュージック
本作は4人対戦ゲームです。
SEをバンバン鳴らしつつCPU負荷を抑えたかったのと、ダウンロードタイトルなので容量を小さくするためにADXを導入しています。
また、ステージの進行状況に合わせてBGMが変化する、インタラクティブミュージックを実装しています。
インタラクティブミュージックは、前述のオクトパストラベラーのようにある曲から別の曲へ「つなぎ曲」を挟みつつダイナミックに変化するものもありますが、今回は一番簡易的な「DAWからトラック別に音源を出力し、ミックスをリアルタイムに変化させる」という手法を取っています。
DAWによる作曲とトラック別の出力
普段のゲーム用作曲ではGarageBandを使っていまして、いまREAPER勉強中なのですが、今回はあまり時間が取れなかったので、iOS向けアプリの「Figure」を使ってループ曲を作り、AIFFファイルに出力してからADXツールに読み込ませ、ゲームに組み込んでいます。
「Figure」はDAWツールの「Reason」を開発しているPropellahead社が開発したアプリです。手軽にループ曲が生成でき、高品質です。(現在は音楽SNS Allihoopaに移管された模様)
曲を「DRUM」「BASS」「LEAD」の3トラックで制作できる簡易ツールなのですが、出力時にトラックを個別にMUTEできます。この機能を使って、曲を作ってからトラック別に3つのAIFFを出力しています。
今回はパリピ感のある音源を使ってパーティっぽい感じの曲を作りました。
QiitaはSoundcloudの埋め込みができないみたいなので、こちらから。音量注意。
「Battle」が3つのトラックをミックスしたもの、only~の3つがバラの音源です。
たぶんこのゲームの製品版には正式利用されないので、テスト用にダウンロードして使ってもOKです。
他のDAWツールを使う場合も、同じようにトラックごとにWAVEやAIFFに出力すればOKです。タイミングはそろっていると楽ですが、難しい場合はあとでADXのツール側でそろえることもできます。
ADXツールへの読み込みと再構成
さて、トラック別に出力した3つの波形データをADXのツール上で再構成します。
上記ゲームでは製品版「ADX」を使っていますが、今回は無償版の「ADX LE」で同じことをやってみています。
事前準備としてADXのCRI Atom Craftで新規プロジェクトを準備し、先程の3つの波形データをマテリアルに登録しておきます。
まず今回使用するキューシートの下にBGM用のキューを作成します。キューシート「CueSheet_0」を選択して右クリックからキュー「ポリフォニック」を新規作成します。名前は「Battle」としておきます。
このとき、右に表示される空のキューにて再生方法が「ポリフォニック」になっていることを確認してください。これはキューを再生したとき、すべてのトラックが同時に再生されることを意味します。
次に、3つのマテリアルをBattleキューの中にドラッグアンドドロップして、曲を再構成します。
ドロップした場所が再生位置となりますが、ドラッグで調整できます。またそれぞれの音量は波形表示の左隣にある青いバーで調整できます。
F5キーを押してキューのプレビュー再生を行い、3つのトラックが同時に再生されることを確認してください。
ゲーム内の何を基準に曲を変化させるか考える
「デモリッション ロボッツ K.K.」は、ロボットが街を破壊していくゲーム内容です。
そのためステージBGMの変化は、街中のビルの残数によって変化する、としました。
ゲーム開始直後はおとなしめで、ビルの数が減ってくるとだんだん盛り上がってくるイメージです。
本作ではUniRxを導入しており、「どのビルがどのロボットに破壊されたか」という情報を流すストリームを走らせて各制御を行っているのですが、その値の発行をフックしてビルが壊されるごとに「いま全体で何パーセント壊されたか」という値を算出し、0f~1fのfloat値をADX側へ渡しています。
ADXツール側のインタラクティブミュージック設定
さきほど作った3つのトラックを持つキューについて、ボリュームのバランスをゲームから動的に変化させる仕組みを作ります。
ADXのもつ「AISAC」という機能を使います。
Advanced Interactive Sound and Active Controllerの略
AISACコントロール値に対応するボリュームやピッチ、フィルタ等のカーブを作成して音色を変化させたりする機能。
例えば、あるキャラクターとの距離をコントロール値とし、その距離に応じたキャラクターのセリフ音量のカーブを描いておくことで、距離に応じた音量をデザインすることができます。
「コントロール値」と言っているのが、ゲームから発行してADX側で受ける制御用の数値のことです。
今回の例では、「どのくらいのビルが破壊されたか」という割合の値になります。
「音量のカーブを描く」とありますが、与えられた値に応じて各トラックの音量をどう変化させるかをカーブ(直線も可能)で設定していくことを意味します。
実際の設定方法ですが、Atom Craftでさきほど設定した「Battle」キューのうち、ひとつトラックを選択して右クリックから「新規オブジェクト」→「AISACの作成」をクリックします。
次のようなダイアログが出ます。
「AISAC名」はトラックごとのAISAC設定の名前です。
「AISACコントロールID」は、プログラムから値を通知するときに指定する名前です。
「AISACグラフタイプ」は操作する音の要素を指定する部分になります。今回は「ボリューム」です。
3つのトラックの音量を同時に操作したいので、それぞれのトラックに「AISACの追加」を行います。さらに、AISACコントロールIDをすべて同じにします。
デフォルトでは「0:AisacControl_00」になっていますので、これを指定して「追加」をクリックします。
(Atom Craftのバージョンによっては、Aisac名が「Any」になっていることもあります。)
画面下部のAISACタブをクリックすると、AISAC設定窓が開き、黄色い線が表示されます。これがAISACコントロール値です。
なおAISACタブをタイムラインと分割表示させておくと後の作業が便利です。
横方向の0から1までの値が、Unityから与える数値を示しています。キューの再生を行いながらツール内で白い棒を左右に動かすとプレビューができます。
まだボリューム変化を何も設定していないので、変化は起きません。
タブ左AISACリストの任意のAISACを選択することでグラフが編集可能になります。このグラフをクリックするとポイントができ、マウスでドラッグすることでボリュームの変化を設定できます。
例として次のようなカーブを作りました。
特に理論だったものはないですが、はじめはBassの音だけ聞こえており、数値が上がるにつれてBassは小さくなりDrumとLeadの音量が上がってきて、終盤はDrumが下がりLeadの主張が大きくなる...という設定にしてみました。
(Leadは「プアープアー」というパリピ感の強い音源にしているので、終盤っぽさがでるかなと....)
なめらかなカーブを作る機能も追加されています。
ポイントの上で右クリックすると、曲線のタイプを選ぶことができます。
最後に、プログラムからこのコントロール値を呼び出しやすいよう、AISACコントロールIDの名前を変えておきます。
Atom Craft左上の「プロジェクトツリー」に現在のAISACコントロール値の一覧があります。
先ほど3つのトラックのAISACコントロール値を「AisacControl_00」に設定したと思いますが、これを判別しやすい名前に変更します。
今回はBGMのミックスを変化させるので、「BgmMixControl」という名前にしてみました。
ここまでできたら、キューシートバイナリをビルドしてUnity Editorにビルドされたデータをコピーします。
(再度注 本エントリーは、ADXをUnityに導入する手順や用語について詳しくは述べていません。はじめてADX / ADX LEを触る方は、前章の「Unityのサウンド機能をADXで強化する」をご確認ください。)
Unity側でAISAC値をコントロールする
Unityでゲームを実行中に、AISACの値を変化させる手順は非常に簡単です。
AISACを設定しているキューを再生中のAtomSourceコンポーネントに対し、SetAisacControl関数で指定します。
public CriAtomSource bgmCriAtomSource;
public void SetValueToBGMAISAC(float aisacValue)
{
bgmCriAtomSource.SetAisacControl("BgmMixControl", aisacValue);
}
なお、ADXのバージョンによってはAisac値が初期化されていなかったり0fが入っていたりします。そうするとAisac設定通りの鳴り方をしない場合がありますので、その際は再生開始時にfloat.Epsilonを与えてあげるとよいでしょう。
設定は以上です。実際にUnity Editor上で曲を鳴らしながら、狙い通りの変化になるようAtom Craft上でグラフの調整を行っていきましょう!