Unityで音楽を再生したり止めたりする設定。
概念
音楽再生機器に、距離の概念を持たせたもの。
●AudioSource : 音源。音楽の再生機器のイメージ。
●AudioClip : 日本語では録音された音声の一部。音楽やサウンド。CDなどのイメージ。
●AudioListener:音声を聞く人。デフォルトではMain Cameraに設置されている。
AudioListenerの使い方は、ここでは触れません。(BGMを流す程度であれば、AudioListener
は Main Camera
に固定でよさそうです。)
一般的な説明として、音楽の再生にはAudioSource
とAudioClip
とがあります。FPSなどに対応するためか、複数のAudioSource
/AudioListener
を使用することで、かなり凝ったことができそうですが、ここでは基本的な操作だけを取り上げます。
主な使い方は、AudioClip
(曲やサウンド)をAudioSource
にセットして、AudioSource
をPlay()
/Stop()
します。
操作
初期化
音源(AudioSource
)は、再生可能な一つのオーディオクリップ(AudioClip
)を持ちます。オーディオクリップを切り替えるには、audioSource
の .clip
にアクセスします。
[SerializeField]
AudioSource audioSource;
[SerializeField]
AudioClip audioClip;
// 音源に曲やサウンドをセットする
audioSource.clip = audioClip;
再生
AudioSource
の Play()
を使用します。
// 再生処理
audioSource.Play();
停止
AudioSource
の Stop()
を使用します。再生中かどうかは .isPlaying
で確認できますが、一時停止でも false
になるため、一時停止を使う場合は、独自の判別フラグを用意する必要があります。
if( audioSource.isPlaying ){
audioSource.Stop();
}
一時停止/再開
AudioSource
の Pause()
と UnPause()
を使用します。先述のようにAudioSource
には一時停止状態かどうかを知る方法がありません。そのため独自の判別フラグを用意する必要があります。
bool paused = false; // 一時停止 if( audioSource.isPlaying ){ if( !paused ){ audioSource.Pause(); paused = true; } } // 再開 if( paused ){ audioSource.UnPause(); paused = false; }
ミュート
AudioSource
の .mute
を使用します。trueでミュートします(Volumeが0になる)。
// ミュート audioSource.mute = true; // ミュート解除 audioSource.mute = false;
フェードイン/アウト
フェードイン・アウトは、少し実装が必要です。以下に実装例を示します。
enum AUDIO_STATE { WAITING, PLAYING, FADING_IN, FADING_OUT, } AUDIO_STATE state; // ボリューム設定値 float audioVolume = -1; // フェードアウト(3秒) float timeRequested = 3.0f; // 残時間 private float timeRemain; void Fadeout() { if( state == AUDIO_STATE.FADING_OUT ) { if( !audioSource.mute ){ audioSource.volume = (float)(audioVolume * (timeRemain / timeRequested)); // audioSource.volume = (float)(audioVolume * (1.0f - timeRemain / timeRequested)); // フェードインの場合 } } } bool Playing() { if( state != AUDIO_STATE.WAITING ){ return true; } return false; } void Update() { if( Playing() ){ if (timeRemain > 0){ timeRemain -= Time.deltaTime; } if (timeRemain <= 0){ timeRemain = 0; Timeout(); } } Fadeout(); }
コード例
あまり凝ったことをしないのであれば、以下のようなコンポーネントを作ることで、複数のBGMを一つのコンポーネントにまとめることができます。
※このコンポーネントを使用する場合、AudioSourceを同じゲームオブジェクトに取り付けてください(コンポーネントの中でAudioSourceを自動取得します)。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public enum BGM_ID { BGM_ID_001, BGM_ID_002, BGM_MAX, // このIDは再生時に指定しない } public class AudioController : MonoBehaviour { // BGM_IDの個数と一致させること [Header("BGM設定")] [SerializeField] List<AudioClip> audioClip; AudioSource audioSource; enum AUDIO_STATE { WAITING, PLAYING, FADING_OUT, } AUDIO_STATE state = AUDIO_STATE.WAITING; // フェードアウト float TIME_FADING_OUT = 3.0f; // ボリューム float audioVolume = -1; // 停止 public void Stop() { if( !ReferenceEquals( audioSource.clip, null) ){ if( audioSource.isPlaying ){ audioSource.Stop(); } } state = AUDIO_STATE.WAITING; if( audioVolume != -1 ){ audioSource.volume = audioVolume; } audioVolume = -1; } // 再生 public void Play( BGM_ID id, float playTime ) { Stop(); audioSource.clip = audioClip[(int)id]; audioSource.Play(); timeRemain = timeRequested = playTime; state = AUDIO_STATE.PLAYING; } bool paused = false; // 一時停止 public void Pause() { if( audioSource.isPlaying ){ if( paused == false ){ audioSource.Pause(); paused = true; } } } // 再開 public void UnPause() { if( paused == true ){ audioSource.UnPause(); paused = false; } } // ミュート public void SetMute( bool onoff ) { audioSource.mute = onoff; } private float timeRequested; private float timeRemain; void Timeout() { if( state == AUDIO_STATE.PLAYING ){ state = AUDIO_STATE.FADING_OUT; if( !audioSource.mute ){ audioVolume = audioSource.volume; timeRemain = timeRequested = TIME_FADING_OUT; } else { state = AUDIO_STATE.WAITING; } } else if( state == AUDIO_STATE.FADING_OUT ){ state = AUDIO_STATE.WAITING; StopBGM(); } } void Fadeout() { if( state == AUDIO_STATE.FADING_OUT ) { if( !audioSource.mute ){ audioSource.volume = (float)(audioVolume * (timeRemain / timeRequested)); } } } // Start is called before the first frame update void Start() { // 音源 audioSource = gameObject.GetComponent<AudioSource>(); } bool Playing() { if( state != AUDIO_STATE.WAITING ){ return true; } return false; } // Update is called once per frame void Update() { if( Playing() ){ if (timeRemain > 0){ timeRemain -= Time.deltaTime; } if (timeRemain <= 0){ timeRemain = 0; Timeout(); } } Fadeout(); } }
呼び出し関数をstaticにできれば、より便利かもしれません。