AudioSourceのPlay()の用途を間違えたらアカン[Unity]
以前,こちらの記事を挙げたと思います. xrdnk.hateblo.jp
AudioManager.csに初歩的なミスがありました. 皆さんはお気づきでしょうか.
using UnityEngine; using System; public class AudioManager : SingletonMonoBehaviour<AudioManager> { // Soundクラス配列 public Sound[] sounds; // シングルトン化 public AudioManager audioManager; private void Awake() { // AudioManagerインスタンスが存在しなければ生成 // 存在すればDestroy, return if (audioManager == null) { audioManager = this; } else { Destroy(this); return; } DontDestroyOnLoad(this.gameObject); // Soundクラスに入れたデータをAudioSourceに当てはめる foreach (Sound s in sounds) { s.audioSource = gameObject.AddComponent<AudioSource>(); s.audioSource.clip = s.clip; s.audioSource.volume = s.volume; } } public void Play(string name) { // ラムダ式 第二引数はPredicate // Soundクラスの配列の中の名前に, // 引数nameに等しいものがあるかどうか確認 Sound s = Array.Find(sounds, sound => sound.name == name); // なければreturn if (s == null) { print("Sound" + name + "was not found"); return; } // あればPlay() s.audioSource.Play(); } }
正解はPlay()メソッド内です.
SEとして再生する場合はPlay()ではなく,PlayOneShot()を使うべきです.
Play()は重複させずに音を鳴らすため,同時に鳴らしたい場合があるSEには合わないです.
どちらかとBGMに使うのが合っています.
勿論,ケース次第でPlay()でSEを鳴らしても問題ない場合もあります.
Play()は今のSEが終わるまで解放されないため,次のPlay()までに遅延が発生します.
例えばプレイヤーが敵に殴られるときに,殴られる音,
ダメージを食らうときの声の音を入れたりしている場合で,
死ぬときに瞬時に叫び声の音を出したくても,
他の音が終わるまで 鳴らないので,おかしなことになったりします.
この初歩的なことを頭から抜けていて,
今作っているゲームのSEのバグに気づくのに数時間かかったので忘備録….
一応,PlayOneShot()を加えた場合のAudioManager.csを載せておきます.
コードが拙くて申し訳ないですが,おまけにStop()も載せておきます.
using UnityEngine; using System; public class AudioManager : SingletonMonoBehaviour<AudioManager> { // Soundクラス配列 public Sound[] sounds; // シングルトン化 public AudioManager audioManager; private void Awake() { // AudioManagerインスタンスが存在しなければ生成 // 存在すればDestroy, return if (audioManager == null) { audioManager = this; } else { Destroy(this); return; } DontDestroyOnLoad(this.gameObject); // Soundクラスに入れたデータをAudioSourceに当てはめる foreach (Sound s in sounds) { s.audioSource = gameObject.AddComponent<AudioSource>(); s.audioSource.clip = s.clip; s.audioSource.volume = s.volume; } } public void Play(string name) { // ラムダ式 第二引数はPredicate // Soundクラスの配列の中の名前に, // 引数nameに等しいものがあるかどうか確認 Sound s = Array.Find(sounds, sound => sound.name == name); // なければreturn if (s == null) { print("Sound" + name + "was not found"); return; } // あればPlay() s.audioSource.Play(); } public void PlayOneShot(string name) { Sound s = Array.Find(sounds, sound => sound.name == name); if (s == null) { print("Sound" + name + "was not found"); return; } s.audioSource.PlayOneShot(s.clip); } public void Stop(string name) { Sound s = Array.Find(sounds, sound => sound.name == name); if (s == null) { return; } s.audioSource.Stop(); s.audioSource.clip = null; } }