【Unity】独自AudioSourceとAudioTimePoliceで音楽再生管理
はじめに
こんにちは、まつさこ です。
この記事では、Unityアプリにおいて独自のAudioSourceクラスを用意し、ゲーム全体の音楽再生を管理しやすくする方法を紹介します。
特に、ゲームポーズ時の一括一時停止/再生や、ゲームスピードが変わった時の一括ピッチ変更などを、サウンド系ミドルウェアを使うことなくUnity標準機能のみで実現したい方におススメしたい方法です。
開発環境
筆者の開発環境は以下です。
- Unity 2021.3.5f1
- Rider 2023.2.3
AudioTimePolice
音楽再生を統括管理する ゲーム全体の音楽再生を管理する「時間警察」、 AudioTimePolice
クラスを作成します。
Staticクラスとして作成します。
using System;
using System.Collections.Generic;
using UnityEngine;
public static class AudioTimePolice
{
//AudioSourceオブジェクトを識別するための <InstanceID, Object> Dictionary
static Dictionary<int, AudioParam> _audioSources = new Dictionary<int, AudioParam>();
static float _pitch = 1;
//独自AudioSourceから呼ばれる
public static void SetDictionary(AudioParam param)
{
var instanceId = param.Audio.gameObject.GetInstanceID();
if (!_audioSources.ContainsKey(instanceId))
{
_audioSources.Add(instanceId, param);
//現在のピッチに設定
if (!param.UnchangeablePitch)
{
param.MyAudio._basePitch = _pitch;
param.Audio.pitch = _pitch;
}
}
else
{
Debug.Log(param.Audio.gameObject.name + " is already in dictionary.");
}
}
//AudioSourceをDictionaryから削除
public static void DeleteFromDictionary(AudioSource audio)
{
if (audio == null)
{
return;
}
var instanceId = audio.gameObject.GetInstanceID();
if (_audioSources.ContainsKey(instanceId))
{
_audioSources.Remove(instanceId);
}
}
//Pause
public static void Pause()
{
foreach (var audio in _audioSources)
{
audio.Value.Audio.Pause();
}
}
//UnPause
public static void UnPause()
{
foreach (var audio in _audioSources)
{
audio.Value.Audio.UnPause();
}
}
//再生スピードを変更
public static void SetSpeed(float pitch)
{
_pitch = pitch;
foreach (var audio in _audioSources)
{
if (!audio.Value.UnchangeablePitch)
{
audio.Value.MyAudio._basePitch = _pitch;
audio.Value.Audio.pitch = _pitch;
}
}
}
//初期化
public static void Initialize()
{
_audioSources = new Dictionary<int, AudioParam>();
_pitch = 1;
}
[Serializable]
public class AudioParam
{
public AudioSource Audio;
public MyAudioSource MyAudio; //後述する独自AudioSourceクラス
public bool UnchangeablePitch; //再生スピードを変更するときにピッチを変えないオプション
}
}
この AudioTimePolice
では、次の項で記載する独自AudioSource MyAudioSource
クラスをもったオブジェクトを保持し、一括でポーズ/ポーズ解除/スピード変更などを行います。
MyAudioSource
をもつオブジェクトが何らかの理由で削除されたときには、正しくDictionaryから削除し、問題が生じないようにしています。
MyAudioSource
独自AudioSource 次のようにスクリプトを作成します。
using System;
using UnityEngine;
[RequireComponent(typeof(AudioSource))]
public class MyAudioSource : MonoBehaviour
{
[SerializeField] bool _unchangeablePitch = false;
[NonSerialized] public float _basePitch;
[NonSerialized] public AudioSource _audio;
void Start()
{
_audio = GetComponent<AudioSource>();
AudioTimePolice.AudioParam param = new AudioTimePolice.AudioParam()
{
Audio = _audio,
MyAudio = this,
UnchangeablePitch = _unchangeablePitch
};
AudioTimePolice.SetDictionary(param);
}
//オブジェクトが削除されたときAudioTimePoliceのDictionaryからも削除
void OnDestroy()
{
AudioTimePolice.DeleteFromDictionary(_audio);
}
}
AudioSource
コンポーネントとセットでオブジェクトにつけます。MyAudioSource
に [RequireComponent(typeof(AudioSource))]
が定義されているので、MyAudioSource
をオブジェクトにアタッチすると自動的に AudioSource
もアタッチされます。
使い方
次の表のように、状況に合わせて関数を呼ぶことで、MyAudioSource
を付けたオーディオオブジェクトすべてを一括操作することが出来ます。
状況 | 呼ぶ関数 | 備考 |
---|---|---|
ゲームをポーズしたとき | AudioTimePolice.Pause() |
|
ポーズを解除したとき | AudioTimePolice.UnPause() |
|
ゲームスピードを変更したとき | AudioTimePolice.SetSpeed(pitch) |
引数 pitch には変化倍率(int)を入れる |
まとめ
この記事では、Unityアプリにおいて独自のAudioSourceクラスを作成し、ゲーム全体の音楽再生を管理しやすくする方法を紹介しました。
ミドルウェアは高くてなかなか手が出ないけれど、音楽再生の管理を楽にしたいときなどに、参考にしてみてください。
読んでくださりありがとうございました🤗
Discussion