Open1
Unity ScriptableObject使用で、mp3イントロ付きループ再生してみました
Unityでイントロ付きmp3をループ再生してみました。色々調べてみましたが標準ではできないため、ScriptableObjectでSoundclipとイントロスキップ箇所を定義した音源用ScriptableObjectを作り、その音源ScriptableObjectを使ってイントロ付きループを実現してみました。
以下のようなファイルで構成しております。
- 音源用ScriptableObject (音源用AudioClipとスキップしたい時間帯を定義)
- BGMループ再生クラス(シーン別BGM制御クラスから受け取った音源用ScriptableObjectを再生する)
- BGMループ制御用インターフェース(シーン別BGM制御クラスで使用、BGMループ再生クラスをオブジェクトで定義する)
- シーン別BGM制御クラス(シーンから呼び出したい音源用ScriptableObjectを指定して、BGMループ再生クラスに受け渡しをする)
まずは音源用ScriptableObjectを作成します。
using UnityEngine;
namespace BGM
{
/// <summary>
/// 音源ループScriptableObject
/// </summary>
[CreateAssetMenu(fileName = "LoopSound", menuName = "ScriptableObjects/LoopSound", order = 1)]
public class LoopSound :ScriptableObject
{
/// <summary>
/// 音源ファイル
/// </summary>
public AudioClip clip;
/// <summary>
/// イントロ部分のスキップ時間帯(秒)
/// </summary>
public float skipTime;
}
}
作成した音源用ScriptableObjectにAudioClipとイントロスキップしたい時間帯を定義します。
次にBGMループ再生クラスを作成します。こちらは実際に音源用ScriptableObjectを受け取り再生するためのClassになります。
using UnityEngine;
namespace BGM
{
/// <summary>
/// BGMループ再生クラス
/// </summary>
public class LoopSoundPlayer : MonoBehaviour
{
[SerializeField] private AudioSource audioSource;
/// <summary>
/// 再生中の音源
/// </summary>
private LoopSound loopSound;
/// <summary>
/// ループ開始地点のサンプル数
/// </summary>
private int loopStartSamples;
/// <summary>
/// ループ終了地点のサンプル数
/// </summary>
private int loopEndSamples;
/// <summary>
/// ループ時間に含まれるサンプル数
/// </summary>
private int loopLengthSamples;
private void Update()
{
// ループ終了地点に達したら、ループ開始地点に戻す
if (audioSource.timeSamples >= loopEndSamples)
{
audioSource.timeSamples -= loopLengthSamples;
audioSource.Play();
}
}
// 外部から音源ScriptableObjectを切り替えるメソッド
public void ChangeLoopSound(LoopSound newLoopSound)
{
// 新しい音源ScriptableObjectを代入する
loopSound = newLoopSound;
// AudioSourceにAudioClipを設定する
audioSource.clip = loopSound.clip;
// AudioClipとskipTimeからサンプル数を計算する
loopStartSamples = (int)(loopSound.clip.frequency * loopSound.skipTime);
loopEndSamples = loopSound.clip.samples;
loopLengthSamples = loopEndSamples - loopStartSamples;
// AudioSourceを再生する
audioSource.Play();
}
}
}
次にBGMループ制御用インターフェースを実装します。こちらはシーン別BGM制御クラスをプロパティにもたせます。
namespace BGM
{
/// <summary>
/// BGMループ制御用インターフェース
/// </summary>
public interface ILoopSoundPlayer
{
LoopSoundPlayer LoopSoundPlayer { get; set; }
}
}
最後にBGMループ制御用インターフェースを実装したシーン別BGM制御クラスを実装します。
こちらはゲーム毎に異なるクラスをそれぞれ定義する想定です。今回はタイトルのみのパターンで実装をしています。こちらはゲームの場面毎に呼び出したいループ音源を定義してカスタマイズすることで、他のシーンなどでも活用できる様になります。
using UnityEngine;
namespace BGM
{
/// <summary>
/// タイトル画面BGM制御クラス
/// </summary>
public class TitleBGMSwitcher : MonoBehaviour, ILoopSoundPlayer
{
/// <summary>
/// タイトルBGM
/// </summary>
[SerializeField] LoopSound titleBGM;
[SerializeField] private LoopSoundPlayer _loopSoundPlayer;
public LoopSoundPlayer LoopSoundPlayer
{
get => _loopSoundPlayer;
set => _loopSoundPlayer = value;
}
private void Start()
{
LoopSoundPlayer.ChangeLoopSound(titleBGM);
}
}
}
実装後任意の要素にAudio Sourceコンポーネントと共にBGMループ再生クラスとシーン別BGM制御クラスを付与して、音源用ScriptableObject、BGMループ再生クラス、Audio Sourceコンポーネントをそれぞれアタッチすればループ付き音源を再生できる様になります。