Unityで効果音とBGMを付ける ―足音の基本と応用―

Unityで効果音とBGMを付ける ―足音の基本と応用―

ゲームのサウンドデザインについて演出技法の観点から興味があったのですが、ゲーム機の性能向上とともに音まわりのプログラムも複雑化している中、実装側の視点からも迫ってみたいと以前から考えていました。

そこで実際にゲーム開発環境のUnityを使って、様々なサウンド関係の演出法と実装について試してみることにしました。始めに効果音の例として「足音」について取り上げてみます。

まずはUnityにおけるオーディオ関係の基本的な機能として、Audio ClipやAudio Source、Audio Listenerといった仕組みを見ていきます。加えてアニメーションに連動して音を再生する方法や、自然に聴かせるために再生にランダム性をもたせる工夫、地面の種類を判定して足音を変える方法について整理してみました。

目次

  1. シーンのAudio Listenerを確認する
  2. Audio Clipをインポートする
  3. Audio Sourceを取り付ける
  4. 効果音を再生するスクリプトを作成する
  5. 足音の再生にランダム性をもたせる工夫
  6. アニメーションに連動して音を再生する
  7. 地面の種類を判定して音を変える(タグ)
  8. 地面の種類を判定して音を変える(Terrainの場合)

1. シーンのAudio Listenerを確認する

Main Cameraに取り付けられているAudio Listener
Main Cameraに取り付けられているAudio Listener

音声を再生するプログラムの命令を実行すると即そのまま音が出力されるかと言うとそうではなく、必ずこのAudio Listenerという仕組みを通って再生されます。

音が右方向で鳴っていれば右寄りに再生したり、音が遠ければ減衰させたりと、ゲーム内で音を出す音源=Audio Sourceとの距離や方向、速度を考慮して音の聞こえ方を変化させる役割をもちます。ゲームの空間内に仮想のマイクを立てて収録するようなイメージです。

Audio Listenerが無いと音が再生されなくなってしまいますが、デフォルトでMain Cameraに取り付けられていて、設定できる項目もないので普段はそれほど気にする必要はないと思います。一人称視点のゲームではカメラよりもプレイヤーに取り付けたほうがいい場合もあるかもしれません。[1]

左:Audio Listenerを取り付けたメインカメラと右:Audio Sourceを取り付けたキャラ
左:Audio Listenerが付いているメインカメラと右:Audio Sourceを取り付けたキャラ

2. Audio Clipをインポートする

Audio Clipの設定項目
Audio Clipの設定項目

Unityではインポートした音声ファイルをAudio Clipとして扱います。ゲーム中で音声を再生するための工夫として、圧縮によってファイル容量を節約したり、再生時の負荷が低い音声フォーマットに変換する場合もありますが、前もって変換をしなくてもUnity上で最適な形式に変換できます。足音のような効果音は基本的にモノラルでも十分なので、もしステレオになってる場合はここで「Force To Mono」にチェックを入れると容量や負荷を減らせます。

小さいサイズの音声で頻繁に再生するので、あらかじめロード時にメモリに展開しておく「Decompress On Load」をLoad Typeに設定しました。逆にBGMやボイスのようにファイル容量が大きく、再生開始するタイミングも限られている音声はストリーミングにするのが基本的な戦略になります。ゲーム進行中に音声を読み出すと負荷が増えたり再生がわずかに遅延するリスクもあるので注意が必要です。

Compression FormatはVorbis (ogg) を使うことが多いですが、足音や衝突音のようにノイズ成分が多くて少し音質が落ちても問題がなく、頻繁に再生するのでCPU負荷を軽くしたい音には「ADPCM」が向いています。[2]

3. Audio Sourceを取り付ける

Audio Clipの設定項目
Audio Clipの設定項目

Audio Clipを読み込んで音を再生するAudio Sourceを音が発生する位置に取り付けます。足音はキャラクターの位置から聞こえて欲しいので、キャラのゲームオブジェクトにAudio Sourceを追加します。オブジェクトを選択してインスペクターのAdd Componentボタンから追加します。

今回は再生する音声ファイルを別で指定するのでAudio Clipは空欄にしておきます。デフォルトではシーンが起動するときに鳴るようになっていますが(Play On Awake)、再生するタイミングも別で指定するのでチェックを外しておきます。Spatial Blendは1(=3D)としてゲーム空間での音源の配置に応じて聞こえ方が変化する設定にしています。Spatial Blend 0(=2D)はBGMやボイスで使う機会が多い設定です。[3]

4. 効果音を再生するスクリプトを作成する

効果音を再生するためのスクリプトを作成して、先ほどのAudio Sourceと同じオブジェクトの同じ位置に取り付けます。(※違う位置に取り付けるとAudio Sourceコンポーネントの参照・取得が面倒になります)

スクリプトで音を再生するときはAudioSourceの関数PlayまたはPlayOneShotを使います。PlayOneShot関数は一度再生すると制御が効かず最後まで鳴る代わりに、複数の音を重ねて再生できます[4]。Play関数は同時に1つしか鳴らない長い音声に、PlayOneShot関数は複数の種類の音が重なる短い音声に適しています。基本的にはBGMやボイスは前者、足音のような効果音は後者に該当します。

5. 足音の再生にランダム性をもたせる工夫

足音のように繰り返し鳴る効果音は耳につきやすく、毎回まったく同じ音声だとマシンガンに例えられるような、機械的で違和感のある音になります。そこで再生する音声ファイルを複数用意したり再生時のピッチを毎回ランダムにして、より自然に鳴るように工夫してみます。

作成したスクリプトの設定
作成したスクリプトの設定

Audio Sourceにも単体のAudio Clipを指定する欄がありましたが、複数の音声は指定できませんでした。そこでスクリプト上にAudio Clipの配列を定義して、複数の音声ファイルを読み込めるようにします。[SerializeField] でシリアライズするとインスペクター上に音声ファイルを指定できる欄が出てきます。

関数Playと異なりPlayOneShotはAudio Clipを引数に取るので、ここで複数の音声ファイルからランダムに選んで渡します。PlayOneShotは音量(float volumeScale)も引数に取ることができるので、発音ごとにランダムに音量を変えるといった使い方もできます[5]。その代わりPlayのように再生途中では音量を変えられません。

再生ピッチはAudio Sourceの変数pitchで設定できます。ピッチはファイル再生ごとではなく音源に対して決まっているので、再生途中でもピッチが変わることに注意してください。

6. アニメーションに連動して足音を再生する

アニメーションイベントの設定画面を開く
アニメーションイベントの設定画面を開く

最後に足音を再生するタイミングを設定します。Animatorウィンドウで各ステートをダブルクリックすると、ステートに設定してあるAnimationのインポート設定がインスペクターに表示されます。少し下の方にあるEventsの項目をクリックすると出てくるのがアニメーションイベントです。

時間の目盛りが付いたイベントライン上で足音を鳴らしたい場所にイベントを追加します。アニメーションイベントのFunctionに先ほど作成した効果音を鳴らすスクリプトの関数を設定すると、アニメーションに連動してこの関数から音を再生することができます。

アニメーションイベントの設定
アニメーションイベントの設定

下のアニメーションのプレビューも参考にしながら、左右それぞれの足が地面に着くタイミングに設定をしました。ここでイベントごとに別の関数を設定すれば、左右の足音を鳴らし分けたり、足音に限らずアニメーションに合わせて複数の種類の音を鳴らすこともできます。

7. 地面の種類を判定して足音を変える(タグを使う)

キャラクターにコライダーを取り付ける
キャラクターにコライダーを取り付ける

地面の種類によって足音を変えるスクリプトを組んでみます。地面の種類の判定にはオブジェクトからマテリアルを取得するなどいろいろな方法が考えられますが、ひとまず簡単にタグを使った方法を試してみようと思います。Terrainを使っている場合は少し特殊な処理が必要なので後ほど紹介します。

地面からの情報の取得にも複数の方法が考えられるのですが、今回はCollider(コライダー)を使ってキャラクターと他オブジェクトのあいだで当たり判定が発生した場合に取得するようにしてみます。キャラクターオブジェクトの中で足元にあたる部分を探して、程よい大きさでSphere Colliderを取り付けます。判定にはトリガーを使うので「Is Trigger」にチェックを付けます。

当たり判定とそのオブジェクトを足音再生のスクリプトに渡す処理を書いて、こちらもコライダーと一緒に取り付けておきます。(transform.root.~の部分は足音再生のスクリプトを参照するように適宜調整してください)

足音を再生するスクリプトに戻って、先ほどの当たり判定が呼び出された時の処理(RelayedTrigger)を書きます。インスペクター上で地面の種類ごとにタグ名と音声ファイルをセットで登録するようにして、スクリプト内では当たり判定時に取得したオブジェクトのタグ名によって読み出す音声ファイルを変更するようにします。

地面の種類ごとにタグ名と音声ファイルを指定
地面の種類ごとにタグ名と音声ファイルを指定

判定に用いるオブジェクト側のタグは、親要素ではなく◯◯Colliderがアタッチされていて接地面になる要素に付ける必要があります。例えばですが、橋のゲームオブジェクトに対しては手すりではなく床面(Box Colliderがアタッチされている)にタグを付けました。

ちなみにこの当たり判定を使って足音を鳴らす方法も考えられるのですが、当たり判定が漏れて鳴らなかったりと制御が難しく、ここではアニメーションイベントを使う方法を紹介しました。

オブジェクト内のColliderが付いた要素に足音判定用のタグを付ける
オブジェクト内のColliderが付いた要素に足音判定用のタグを付ける

8. 地面の種類を判定して足音を変える(Terrainの場合の処理)

Terrainに使われているテクスチャーの一覧
Terrainに使用されているテクスチャーの一覧

Terrainでも地面の種類を判定して足音を変えたいところですが、実際は何種類かのテクスチャーの合成で表現されているので少し複雑な処理が要ります。インスペクター上のTerrainからPaint Textureを選ぶと、今使用しているテクスチャーの一覧がTerrain Layersとして表示されます。

この複数のテクスチャーを合成するための情報が入っているのがAlphamapです。Terrainに対するAlphamapのスケールに応じて変換した座標を指定して、現在地のテクスチャーの合成情報を取得します。ここではアルファマップのうち最大の成分となるテクスチャーを足音の判定に使うことにします。

Terrain Layersと足音の種類の対応を記述しておきます
Terrain Layersと足音の種類の対応を記述しておきます

おわりに

実際に鳴らしてみたのがこちらです。土・草地・木の3種類、それぞれ5個の音声を効果音素材集から切り出してみました。素材集はあらかじめ使いやすいように加工してあったりしますが、録音したままの音だとマイクを近づけて録るので近接効果で低域が出過ぎてる場合もあるかもしれません。そういったときはUnityにインポートする前に音声編集ソフトでバッサリとカットするのがおすすめです。

SDユニティちゃん: © Unity Technologies Japan/UCL