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

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

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

👉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を別々のファイルにする実装が多いです。
作り方はどちらでも良いと思いますが、
サウンドクリエーターの作りやすい方法を
採用できるのが良いのかなと思います。

オススメ記事
検証環境