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;
    }
}