Unity で BGM とアナウンスを同時再生する方法【ダッキング付き】

Unity でゲームを作っていると、「それっぽさ」を出したくなります。

今回は、レース前の演出として

  • BGM を流す
  • 少し待ってからアナウンスを流す
  • アナウンス中は BGM を少し下げる(ダッキング)

という仕組みを実装してみました。

シンプルですが、これだけで一気に雰囲気が出ます。

デモ

最終的な音声はこちらです。

音量変化のイメージ

今回の処理では、BGM を流したままアナウンスを再生しています。

ただし、そのままだとアナウンスが聞き取りにくくなるため、
アナウンス再生中だけ BGM の音量を下げています。

流れとしては次の通りです。

  1. BGM を通常音量で再生
  2. アナウンス直前に BGM を少し下げる
  3. アナウンス再生中はそのまま維持
  4. アナウンス終了後に BGM を元の音量へ戻す

図にすると、BGM と Voice の音量変化は次のようになります。

音量変化 通常 アナウンス直前 アナウンス中 終了後 Voice BGM

Unity での実装

ポイントは3つです。

  1. AudioSource を2つ使う(BGM 用 / Voice 用)
  2. コルーチンで順番に制御する
  3. BGM の音量をフェードさせる(ダッキング)

コード

using System.Collections;
using UnityEngine;

public sealed class SampleAudioPlayer : MonoBehaviour
{
    [SerializeField] AudioSource bgmSource;
    [SerializeField] AudioSource voiceSource;

    [SerializeField] AudioClip bgmClip;
    [SerializeField] AudioClip voiceClip;

    [SerializeField, Min(0f)] float voiceDelaySeconds = 0.8f;

    [SerializeField, Min(0f)] float BgmNormalVolume = 0.4f;
    [SerializeField, Min(0f)] float BgmDuckVolume = 0.2f;
    [SerializeField, Min(0f)] float DuckDurationSeconds = 0.3f;
    [SerializeField, Min(0f)] float RestoreDurationSeconds = 0.5f;

    void Start()
    {
        StartCoroutine(PlaySequence(voiceClip));
    }

    private IEnumerator PlaySequence(AudioClip clip)
    {
        PlayBgm();
        yield return new WaitForSeconds(voiceDelaySeconds);
        yield return PlayVoiceWithDuck(clip);
    }

    private void PlayBgm()
    {
        bgmSource.clip = bgmClip;
        bgmSource.loop = true;
        bgmSource.volume = BgmNormalVolume;
        bgmSource.Play();
    }

    private IEnumerator PlayVoiceWithDuck(AudioClip clip)
    {
        yield return bgmSource.FadeTo(BgmDuckVolume, DuckDurationSeconds);

        voiceSource.clip = clip;
        voiceSource.loop = false;
        voiceSource.Play();

        yield return new WaitWhile(() => voiceSource.isPlaying);

        yield return bgmSource.FadeTo(BgmNormalVolume, RestoreDurationSeconds);
    }
}

public static class AudioSourceExtensions
{
    public static IEnumerator FadeTo(this AudioSource source, float target, float duration)
    {
        float start = source.volume;
        float time = 0f;

        while (time < duration)
        {
            time += Time.deltaTime;
            source.volume = Mathf.Lerp(start, target, time / duration);
            yield return null;
        }

        source.volume = target;
    }
}

素材

BGM

Aesthetics Of Stoppage
by Lui_Epicmusic (Pixabay)

Voice

VOICEVOX: No.7