こんにちは、開発の半沢 匠です。
今回もUnity(http://unity3d.com/)に関しての記事を書きたいと思います。
今回もUnity(http://unity3d.com/)に関しての記事を書きたいと思います。
■音管理
ゲーム開発及び、アプリ開発において
音再生は欠かせないもの。
BGMやSEを導入するだけで、ぐっと雰囲気が出てきます。
今回はこれをなるべく簡単に管理できるような仕組みを紹介したいと思います。
■スクリプト
SoundManager.csという下記のスクリプト作成いたしましたので、
こちらを紹介させていただきます。
using UnityEngine;
using System;
using System.Collections;
// 音管理クラス
public class SoundManager : MonoBehaviour {
protected static SoundManager instance;
public static SoundManager Instance
{
get
{
if(instance == null)
{
instance = (SoundManager) FindObjectOfType(typeof(SoundManager));
if (instance == null)
{
Debug.LogError("SoundManager Instance Error");
}
}
return instance;
}
}
// 音量
public SoundVolume volume = new SoundVolume();
// === AudioSource ===
// BGM
private AudioSource BGMsource;
// SE
private AudioSource[] SEsources = new AudioSource[16];
// 音声
private AudioSource[] VoiceSources = new AudioSource[16];
// === AudioClip ===
// BGM
public AudioClip[] BGM;
// SE
public AudioClip[] SE;
// 音声
public AudioClip[] Voice;
void Awake (){
GameObject[] obj = GameObject.FindGameObjectsWithTag("SoundManager");
if( obj.Length > 1 ){
// 既に存在しているなら削除
Destroy(gameObject);
}else{
// 音管理はシーン遷移では破棄させない
DontDestroyOnLoad(gameObject);
}
// 全てのAudioSourceコンポーネントを追加する
// BGM AudioSource
BGMsource = gameObject.AddComponent<AudioSource>();
// BGMはループを有効にする
BGMsource.loop = true;
// SE AudioSource
for(int i = 0 ; i < SEsources.Length ; i++ ){
SEsources[i] = gameObject.AddComponent<AudioSource>();
}
// 音声 AudioSource
for(int i = 0 ; i < VoiceSources.Length ; i++ ){
VoiceSources[i] = gameObject.AddComponent<AudioSource>();
}
}
void Update () {
// ミュート設定
BGMsource.mute = volume.Mute;
foreach(AudioSource source in SEsources ){
source.mute = volume.Mute;
}
foreach(AudioSource source in VoiceSources ){
source.mute = volume.Mute;
}
// ボリューム設定
BGMsource.volume = volume.BGM;
foreach(AudioSource source in SEsources ){
source.volume = volume.SE;
}
foreach(AudioSource source in VoiceSources ){
source.volume = volume.Voice;
}
}
// ***** BGM再生 *****
// BGM再生
public void PlayBGM(int index){
if( 0 > index || BGM.Length <= index ){
return;
}
// 同じBGMの場合は何もしない
if( BGMsource.clip == BGM[index] ){
return;
}
BGMsource.Stop();
BGMsource.clip = BGM[index];
BGMsource.Play();
}
// BGM停止
public void StopBGM(){
BGMsource.Stop();
BGMsource.clip = null;
}
// ***** SE再生 *****
// SE再生
public void PlaySE(int index){
if( 0 > index || SE.Length <= index ){
return;
}
// 再生中で無いAudioSouceで鳴らす
foreach(AudioSource source in SEsources){
if( false == source.isPlaying ){
source.clip = SE[index];
source.Play();
return;
}
}
}
// SE停止
public void StopSE(){
// 全てのSE用のAudioSouceを停止する
foreach(AudioSource source in SEsources){
source.Stop();
source.clip = null;
}
}
// ***** 音声再生 *****
// 音声再生
public void PlayVoice(int index){
if( 0 > index || Voice.Length <= index ){
return;
}
// 再生中で無いAudioSouceで鳴らす
foreach(AudioSource source in VoiceSources){
if( false == source.isPlaying ){
source.clip = Voice[index];
source.Play();
return;
}
}
}
// 音声停止
public void StopVoice(){
// 全ての音声用のAudioSouceを停止する
foreach(AudioSource source in VoiceSources){
source.Stop();
source.clip = null;
}
}
}
更に音量クラスも作成する。
// 音量クラス
[Serializable]
public class SoundVolume{
public float BGM = 1.0f;
public float Voice = 1.0f;
public float SE = 1.0f;
public bool Mute = false;
public void Init(){
BGM = 1.0f;
Voice = 1.0f;
SE = 1.0f;
Mute = false;
}
}
■使用手順
1.上記のSoundManager.csを空のオブジェクトに張り付ける。
2.オブジェクトのタグ名を”SoundManager”とする。
3.追加したい音ファイルをGUI操作で追加する(下図参照)
4.音を再生したい箇所に下記ソースを、それぞれ追加する。
SoundManager.Instance.PlayBGM(0); SoundManager.Instance.PlaySE(2); SoundManager.Instance.PlayVoice(3);
以上で音を再生できるようになったかと思います。
■解説
・SoundManagerは、1シーンに1つのみ生成されるようになっており、
シーン遷移時でも破棄されないように設定されており、
シングルトン化してある為、どのソースからもアクセス可能になっております。
・エディタ上でドラッグ&ドロップだけで音ファイルを簡単に追加/削除できるため、
プログラマー以外の人でも簡単に使えるように想定(別途エクセル等でインデックス管理はした方が良い)
また、鳴らす際も1行のソースを追加するだけの簡単仕様にしました。
・new AudioSource[16];は16個まで同時再生可能という設定になっております。
こちらは状況に応じて色々と変更されると良いかもしれません。
・SoundVolumeに[Serializable]を追加することで、エディタ上に音量やミュート状態を表示するようにし、デバッグ時に使用できるように致しました。
■最後に
よくある手法ではございますが、こんな感じに私は使用しておりますという事でご紹介させていただきました。
結構便利な機能だと思いますので、是非ご活用頂ければと思います。
Ver.βということで今後も随時使いやすい形に改良していきたいと思います。

最近unityを使い始めました。
返信削除有用なスクリプトありがとうございます。
修正済みかもしれませんが、気になりましたのでお知らせまで。
101: if( 0 > index || BGM.Length <= index ){
→ if( 0 >= index && BGM.Length < index ){
123: if( 0 > index || SE.Length <= index ){
→ if( 0 >= index && SE.Length < index ){
かと思います。
コメントありがとうございます。
返信削除ご指摘いただいた件につきまして、
プログラムの意味としましては、
indexが範囲外の場合に何も処理しない
という意味になりますので、このままで問題ないかと思います。
シーンを遷移すると、遷移先のシーンにSoundManagerタグをつけたGameObjectがあっても
返信削除音管理が破棄されないんですが、私の環境が悪いんでしょうか。
コメントありがとうございます。
返信削除こちらでは、上記ソースで削除されることを確認致しました。
タグのつけ忘れやSoudの等の誤字はございませんでしょうか。
参考にさせて頂き、自分もSoundManager作りました。
返信削除http://qiita.com/waken/items/a0288c9b160a20022635
ありがとうございます。
とても便利です!ありがとうございます!
返信削除