ゲームをプレイするときに再生されるサウンド音量は各々の環境で全く異なります。
そのため、ボリュームの制御を行うのはどのゲームでも必須といっていいものです。
今回はボリュームの制御について見ていきたいと思います。
コンテンツ
要件
3Dゲームでは空間にオーディオが配置される上にプレハブの生成によって動的に変化します。
そのため
- 動的に生成されるオーディオをすべて管理しなければならない
- オーディオが破棄されたことを管理しなければならない
- ボリュームが変化されたときに速やかにオーディオに伝えなければならない
このような要件が必要になります。
実装方法
単純に以下のプロセスを事前出来れば解決できる
このようにボリューム変更を一度「ボリューム管理者」を置いて手続きするとここからボリュームガン変更されたとき「ボリューム変更者」がボリュームを変更することで比較的容易に実現できます。
ということでボリューム管理者とボリューム変更者を実装します。
↓ボリューム管理者
public class VolumeManager : MonoBehaviour
{
/// <summary>インスタンス</summary>
private static VolumeManager instance = null;
/// <summary>ボリュームタイプ</summary>
public enum VolumeType
{
None,
Se,
Bgm,
}
public static VolumeManager Instance
{
get
{
if(instance == null)
{
var obj = new GameObject();
obj.name = typeof(VolumeManager).Name;
instance = obj.AddComponent<VolumeManager>();
DontDestroyOnLoad(obj);
}
return instance;
}
}
// ----------------------------------------------
// 内部メンバ変数
// 管理してるボリューム変更者
private Dictionary<int, VolumeChanger> m_changers = new Dictionary<int, VolumeChanger>();
// 管理してるボリューム値
private Dictionary<VolumeType, int> m_volumes = new Dictionary<VolumeType, int>();
/// <summary>
/// ボリューム取得
/// </summary>
/// <param name="type">ボリュームタイプ</param>
/// <returns>ボリューム</returns>
public float GetVolume(VolumeType type)
{
if(!m_volumes.ContainsKey(type))
{
m_volumes.Add(type, PlayerPrefs.GetInt(type.ToString(), 50));
}
return m_volumes[type] / 100.0f;
}
/// <summary>
/// ボリュームセット
/// </summary>
/// <param name="type">ボリュームタイプ</param>
/// <param name="volume">ボリューム</param>
public void SetVolume(VolumeType type, int volume)
{
PlayerPrefs.SetInt(type.ToString(), volume);
if(!m_volumes.ContainsKey(type))
{
m_volumes.Add(type, volume);
}
else
{
m_volumes[type] = volume;
}
foreach(var changer in m_changers.Where((a) => a.Value.VolumeType == type))
{
changer.Value.Audio.volume = GetVolume(changer.Value.VolumeType);
}
}
/// <summary>
/// 変更者を登録
/// </summary>
/// <param name="volumeChanger">変更者</param>
/// <returns>管理ID</returns>
public int RegistChanger(VolumeChanger volumeChanger)
{
int max = 1;
if(m_changers.Count > 0)
{
max = m_changers.Max((a) => a.Key) + 1;
}
volumeChanger.Audio.volume = GetVolume(volumeChanger.VolumeType);
m_changers.Add(max, volumeChanger);
return max;
}
/// <summary>
/// 登録者削除
/// </summary>
/// <param name="id">管理ID</param>
public void DeleteChanger(int id)
{
if(m_changers.ContainsKey(id))
{
m_changers.Remove(id);
}
}
}
ボリューム管理者はシングルトンで実装しどこからでもアクセスできるようにします。
↓ボリューム変更者
[RequireComponent(typeof(AudioSource))]
public class VolumeChanger : MonoBehaviour
{
// ----------------------------------------------
// 設定項目
// ボリュームタイプ
[SerializeField]
private VolumeManager.VolumeType m_volumeType = VolumeManager.VolumeType.None;
// ----------------------------------------------
// 内部メンバ変数
// ID
private int m_id = 0;
// オーディオ
private AudioSource m_audio = null;
// ----------------------------------------------
// アクセサ
public AudioSource Audio
{
get
{
if(m_audio == null)
{
m_audio = GetComponent<AudioSource>();
}
return m_audio;
}
}
public VolumeManager.VolumeType VolumeType
{
get
{
return m_volumeType;
}
}
private void Awake()
{
m_id = VolumeManager.Instance.RegistChanger(this);
}
private void OnDestroy()
{
VolumeManager.Instance.DeleteChanger(m_id);
}
}
あらかじめアタッチしておけば、プレハブが生成されたとき「Awake」から自動的に「ボリューム管理者」に登録イベントが発生し、廃棄時に自動的に登録が破棄されます。
また、
[RequireComponent(typeof(AudioSource))]
こうすることで、このスクリプトはAudioSourceが必須になりたいていの場合は必ず存在することになります。
まとめ
概要の通り
ゲームをプレイするときに再生されるサウンド音量は各々の環境で全く異なります。
そのため、ボリュームの制御を行うのはどのゲームでも必須といっていいものです。
配信を行う場合は、必ずボリュームの設定画面を実装しておき、操作できるようにしておきましょう。
次は実際に使用していきたいと思います。
コメントを残す