CRI ADX2(Unity)
フィールド上の大きな川や森の環境音を表現する

 

木にとまる鳥や焚き火など小さいオブジェクトに音をつける場合、
3D空間の座標1点に音源を置いても違和感はありません。

しかし流れる川や風が吹く森の中など巨大なオブジェクトに音をつける場合は
小さいオブジェクトに比べて工夫が必要です。

今回の記事ではADXとUnityのAPIを組み合わせることで、
フィールド上の大きな森や川の環境音を表現する方法を紹介します。

 

事前知識:面音源とは?

ゲーム制作における面音源は、部屋全体やキャラクターよりも大きいような
オブジェクト全体から聞こえる音をさします。
例えばフィールド上の大きな森や川、海などが例に挙げられます。

今回使用するADXの機能

面音源を表現するには点音源をたくさん敷き詰めることで再現できますが、
サウンドデザインの手間やパフォーマンスの観点から現実的ではありません。
ではどうすればよいのでしょうか。

例えば、大きな川を表現してみます。
大きな川の中に点音源(3Dポジショニングが有効なAtom Source)を1つだけ配置し、
この点音源の位置をキャラクターと一番近い場所へ常に移動させます。
こうすることでキャラクターの耳には常に川の側面から音が届くので面音源のように聞こえます。

では実際に試してみましょう!

 

サウンドデータの準備

まずは再生するサウンドデータをCRI Atom Craftで作成しましょう。

1. 使用するキューの「3Dポジショニング」を有効にします。

2. 距離減衰で音量がゼロになる際CPU負荷が減るように、
  「ボイスビヘイビアー」を「仮想ボイス(Vol:0停止、復帰時時刻経過あり)」に設定します。

サウンドデータをビルドし、Unityプロジェクトにサウンドデータを取り込んだら
次はUnityでの設定です。

Unityシーンの準備

  1. シーンに音源となるエリアをコライダーで囲みます。
    • 今回のサンプルでは青と緑のPlaneを配置し、川と森にします
    • Planeの音が出る範囲にColliderを配置します
  2. そのエリア内にCriAtomSourceをそれぞれ配置します。
  3. 以下のCriAtomSourceを移動するためのスクリプトを作成します。
    • 今回の例では、AtomSourceManipulator.csとします。
    • コライダーの中にあるCriAtomSourceをリスナーの位置に移動させるスクリプトです。
    • リスナーがコライダーの外にいると、CriAtomSourceはリスナーに最も近い位置へ移動します。
    • 対してリスナーがコライダーの中にいると、CriAtomSourceはリスナーを追跡します。
> AtomSourceManipulator.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using CriWare;

// シーン中の GameObject にアタッチして利用します。
// 設定された Collider リスト中で CriAtomListner に最も近い位置に
// 指定の CriAtomSource を移動させます。
public class AtomSourceManipulator: MonoBehaviour
{
    // 制御対象の CriAtomSource
    public CriAtomSource atomSource;
    // 比較対象の CriAtomListener
    public CriAtomListener listener;
    // CriAtomSource が内部で動く Collider のリスト
    public List<Collider> colliders;

    void Update()
    {
        if (colliders.Count == 0 || listener == null || atomSource == null)
        {
            return;
        }

        // 設定された Collider から CriAtomListener との最近傍点を計算。
        float minMagnitude = float.MaxValue;
        Vector3 minVector = Vector3.zero;
        var listenerPosition = listener.transform.position;
        
        for (int i = 0; i < colliders.Count; i++)
        {
            var closestPoint = colliders[i].ClosestPoint(listenerPosition);

            var dist = (listenerPosition - closestPoint).magnitude;
            if (dist < minMagnitude)
            {
                minMagnitude = dist;
                minVector = closestPoint;
            }
        }

        // 最近傍点に CriAtomSource を移動。
        atomSource.transform.position = minVector;
    }
}

森と川それぞれのゲームオブジェクトにAtomSourceManipulatorをアタッチしてシーンに配置しましょう。
次にAtomSourceManipulatorのインスペクター上に

  • CriAtomSource(面音源の役割をする点音源)
  • CriAtomListener(リスナー)
  • Collider(コライダー)

を紐づけます。

以上で設定が終わりました。
では実際に実行してみましょう!

シーンの実行中、音源はコライダー(動画では川と森)の中に閉じ込められます。
音源はフィールドを歩いているりんごちゃん(リスナー)と一番近い場所へ常に移動しています。
りんごちゃんがコライダーの中に入ると、音源はりんごちゃんと同じ位置に追従します。

これで2つ音源だけで大きな川と森が表現できましたね!

Tips

大きな物体から離れたら音が消えてほしい

CRI Atom Craft上で、キューのインスペクターから距離減衰の距離を設定しましょう。
注意点として、今回の実装では「リスナーが面音源範囲の外に居る時」だけ距離減衰になります。
範囲内になると音源がリスナーに追跡するので減衰しません。気を付けましょう!

曲がった川を面音源としたい

複数のColliderを組み合わせたような、曲がった川を面音源としたい場合も設定可能です。
AtomSourceManipulator.csのcollidersは複数のColliderをリスト形式で登録できます。

AtomSourceManipulatorのインスペクター上に追加しましょう!