【Unity】BGMや効果音が途切れるとき

投稿者: | 2021-04-30

シーンが重くなってくると、オーディオソースで再生するBGMや効果音が途切れたり、時間がたってから急に再開したりと不具合が増えました。

原因は、同じオブジェクトに複数のオーディオソースをつけていることのようです。オーディオソースを一つずつ付けるようにすると解消しました。

オーディオソースを一つ付けるだけのゲームオブジェクトをいくつか用意することになりましたが、状況によって必要なオーディオソースの数は変わります。

そこで、スクリプトでプレイ中にオーディオソースを簡単に増やせるようにしました。それには、新規の空のゲームオブジェクトにオーディオソースを追加するだけです。

新規ゲームオブジェクト

作ったオーディオソースをリストに追加しておいて、インデックスを指定して再生や停止、オーディオソースオブジェクトの削除などをできるようにすると便利です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioSourceTest : MonoBehaviour
{
    static AudioSourceTest instance;
    public static AudioSourceTest GetInstance()
    {
        return instance;
    }

    private void Awake()
    {
        if (instance != null) Destroy(gameObject);
        else instance = this;
    }

    // オーディオクリップの配列
    [SerializeField] AudioClip[] audioClips;

    // オーディオソースのリスト
    List<AudioSource> audioSources = new List<AudioSource>();

    // オーディオソースを追加
    public AudioSource AddAudioSource()
    {
        // 新しいゲームオブジェクト
        GameObject obj = new GameObject();

        // オーディオソースを追加
        AudioSource a = obj.AddComponent<AudioSource>();

        // オーディオソースの設定
        a.playOnAwake = false;
        a.loop = false;
        a.volume = 1f;

        // リストに追加
        audioSources.Add(a);

        return a;
    }
    
    public void AddAudioSource(AudioSource a)
    {
        audioSources.Add(a);
    }

    // 再生
    public void PlayAudio(int audioSourceIndex, int clipIndex, float volumeScale = 1f)
    {
        // インデックスが範囲内のとき
        if (audioSources.Count > audioSourceIndex && audioClips.Length > clipIndex)
        {
            // オーディオソースとクリップを指定して再生
            audioSources[audioSourceIndex].PlayOneShot(audioClips[clipIndex], volumeScale);
        }
    }

    // 停止
    public void StopAudio()
    {
        foreach(var a in audioSources)
        {
            a.Stop();
        }
    }

    // オーディオソースを削除
    public void DeleteAudioSource(int index)
    {
        // インデックスが範囲内のとき
        if (audioSources.Count > index)
        {
            // オーディオソースオブジェクトを削除
            Destroy(audioSources[index].gameObject);

            // リストから削除
            audioSources.RemoveAt(index);
        }
    }

    // Start is called before the first frame update
    void Start()
    {
        
    }

}

さらに、オーディオクリップもこのスクリプトにまとめておきました。

これで上の動画のように簡単にオーディオソースを増やせました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestScript2 : MonoBehaviour
{
    int n;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        // 左クリック
        if(Input.GetMouseButtonDown(0))
        {
            // オーディオソースを追加
            AudioSourceTest.GetInstance().AddAudioSource();

            // ランダムで再生
            AudioSourceTest.GetInstance().PlayAudio(n, Random.Range(0,4));
            n++;
        }
        // 右クリック
        else if(Input.GetMouseButtonDown(1))
        {
            // オーディオソースを削除
            AudioSourceTest.GetInstance().DeleteAudioSource(3);
            n--;
        }
    }
}

コメントを残す

メールアドレスが公開されることはありません。