こんにちは、エンジニアのオオバです。

ゲームにはBGMがつきものです。
BGM再生システムにイントロ付きBGMが
ほしいという依頼をもらうことありませんか?

本記事では初心者向けに
イントロ付きループBGMの実装概要について
解説していきます。

→11万文字で徹底解説した「DOTweenの教科書」Unityアニメーションの超効率化ツールはこちら

イントロBGMの再生フロー

イントロのついたBGMは、だいたい以下のようなフローになると思います。
(カッコ内の秒数はイメージしやすくするため仮の数値です)

  1. イントロ (0〜20秒地点までのメロディー)
  2. イントロ以降のメロディー (20秒地点以降のメロディー)
  3. BGM終了 (130秒地点で終了)
  4. ループポイントに戻って再生 (20秒地点から再生再開)
  5. BGM終了 (130秒地点で終了)
  6. ループポイントに戻って再生 (20秒地点から再生再開)

ループが延々に続く。

このイントロが存在するBGMを最小限のコードで実装してみました。

AudioClipとBGM定義ファイルのセット

まずは再生させたいAudioClipとその定義が必要です。

AudioClipとはUnityにインポートした音声ファイルです。
AudioClipをAudioSourceにセットして再生します。

定義には以下の情報を保持させます。

この定義クラスとAudioClipがセットになったSoundInfoクラスを作り、
それをSoundManagerクラスが保持します。

// BGM定義クラス  
public class BgmDefine  
{
 // BGMのスタート時間  
 public float startTime;  

 // ループポイント時間  
 public float loopTime;  

 // BGMの終了時間  
 public float endTime;  
}
// BGM定義情報とAudioClipをセットしたクラス  
public class SoundInfo  
{
 public BgmDefine define;  
 public AudioClip clip;  
}

BGMの再生を開始させたらSoundManagerのUpdate関数で
現在のBGMの再生時間を監視し、終了時間が来たらループ時間へジャンプさせます。

void Update ()  
{
 // 再生中のBGMの再生時間を監視する  
 if (_currentBgmDefine != null && _currentBgmSource != null && _currentBgmSource.isPlaying) {  
  if (_currentBgmSource.time >= _currentBgmDefine.endTime) {  
   // ループポイントへジャンプ  
   _currentBgmSource.time = _currentBgmDefine.loopTime;  
  }
 }
}

以下全ソースです。
Main.csは、SoundManagerに再生させたいAudioClipと
定義情報を渡しています。実際に使用するのはSoundManager.csだけです。
イントロ実装SoundManager · GitHub

まとめ

このサンプルでは1つのAudioSourceで実装しているため、
複数のBGMを同時再生できません。
※例えばクロスフェードでBGMが切り替わるなどの表現は出来ません。
もちろんBGMを再生中にSEも鳴らすことは出来ません。

このあたりは改修が必要ですね。

またBGMをアセットバンドルで使う場合は、
定義ファイル自体もアセットバンドル化させます。
JSONやScriptableObjectなどにして、
BGMとセットでダウンロードして使うことになると思います。

イントロ付きのBGM実装についてググってみると、
イントロ部分のBGMとループ部分のBGMを別々のファイルにする実装が多いです。
作り方はどちらでも良いと思いますが、
サウンドクリエーターの作りやすい方法を
採用できるのが良いのかなと思います。

オススメ記事
検証環境