控制同時播放的音效數量

更新頁 :
頁面創建日期 :

驗證環境

窗戶
  • 視窗 11
統一編輯器
  • 2021.3.3f1
輸入系統包
  • 1.3.0

此提示的先決條件

作為此提示描述的前提,已預先進行了以下設置。

關於樣品中包含的材料

音效是從以下網站借來的。

關於音訊檔

可以使用 Unity 的標準功能播放以下音訊檔案格式: 請提前準備,因為它將在這些提示中使用。

  • 波浪 (.wav)
  • 奧格沃比斯 (.ogg)
  • MPEG 第 3 層 (.mp3)

有關更多資訊,請參閱官方 Unity 文件。

關於多個同時播放音訊的上限和音量

在前面的提示中, AudioClip 現在可以通過在 中準備 AudioSource.PlayOneShot 音訊數據時播放多個語音來播放多個語音。 但是,可以玩的遊戲數量沒有限制,因此如果您在遊戲過程中不限制它,可能會播放很多聲音並且可能會播放很大的音量。

在這裡,我想創建自己的程式並控制可以同時播放的音效數量。

創建範例

這一次,每次按兩下按鈕時都會播放音效,因此請創建如圖所示的UI。 細節是適當和好的。

拖放要播放的音訊檔並將其添加到專案中。

直到上次,標準功能 AudioSource 被添加到層次結構中, 這一次,我們將添加一個腳本,因為我們將放置自己的控件。 SoundPlayManager 將名稱保留為 。

依如下方式建立文稿:

using System.Collections.Generic;
using UnityEngine;

/// <summary>音声再生管理クラスです。</summary>
public class SoundPlayManager : MonoBehaviour
{
  /// <summary>1つの種類の音声の再生情報を保持するクラスです。</summary>
  private class PlayInfo
  {
    /// <summary>再生している AudioSource の一覧です。</summary>
    public AudioSource[] AudioSource { get; set; }

    /// <summary>現在の再生インデックスです。</summary>
    public int NowIndex { get; set; }
  }

  /// <summary>再生しようとしている音声データのキューです。</summary>
  private HashSet<AudioClip> Queue = new HashSet<AudioClip>();

  /// <summary>再生している音声を管理している一覧です。</summary>
  private Dictionary<AudioClip, PlayInfo> Sources = new Dictionary<AudioClip, PlayInfo>();

  /// <summary>
  /// 同一音声同時再生最大数。
  /// </summary>
  [SerializeField, Range(1, 32)] private int MaxSimultaneousPlayCount = 2;

  protected void Update()
  {
    foreach (var item in Queue)
    {
      AudioSource source;
      if (Sources.ContainsKey(item) == false)
      {
        // 一度も再生されていない Clip がある場合は PlayInfo を生成します
        var info = new PlayInfo()
        {
          AudioSource = new AudioSource[MaxSimultaneousPlayCount],
        };
        for (int i = 0; i < MaxSimultaneousPlayCount; i++)
        {
          var s = gameObject.AddComponent<AudioSource>();
          s.clip = item;
          info.AudioSource[i] = s;
        }
        Sources.Add(item, info);
        source = info.AudioSource[0];
      }
      else
      {
        // 再生に使用する AudioSource を順番に取得します
        var info = Sources[item];
        info.NowIndex = (info.NowIndex + 1) % MaxSimultaneousPlayCount;
        source = info.AudioSource[info.NowIndex];
      }

      source.Play();
    }
    Queue.Clear();
  }

  /// <summary>
  /// 効果音を再生します。
  /// </summary>
  public void Play(AudioClip clip)
  {
    // 同一フレームで複数再生しないようにすでにキューに入っているか確認します
    if (Queue.Contains(clip) == false)
    {
      Queue.Add(clip);
    }
  }

  public void OnDestroy()
  {
    // 不要になった参照をすべて外します
    foreach (var source in Sources)
    {
      source.Value.AudioSource = null;
    }
    Sources.Clear();
    Queue.Clear();
  }
}

由於腳本較長,省略了詳細說明,但它具有以下功能。

  • AudioClip 您可以通過傳遞播放音訊
  • 當相同類型的音訊相互疊加播放時,如果嘗試播放超過一定數量的聲音,則舊的播放數據將停止(初始值最多播放 2 次)。
  • 不允許在同一幀上重疊播放

這可以防止在背靠背播放相同音訊時音量增加。 在功能方面,僅包含最低限度,因此如果需要,請添加它。

該腳本將附加到事件系統。

接下來,為按鈕創建腳本。

依如下方式建立文稿:

using UnityEngine;

public class ButtonEvent : MonoBehaviour
{
  /// <summary>再生する音声データ。</summary>
  [SerializeField] private AudioClip AudioClip;

  /// <summary>自作した音声再生管理クラス。</summary>
  [SerializeField] private SoundPlayManager SoundPlayManager;

  /// <summary>ボタンをクリックしたとき。</summary>
  public void OnClick()
  {
    SoundPlayManager.Play(AudioClip);
  }
}

播放過程由自製 SoundPlayManager 自己完成,因此在按鈕事件中,只需傳遞音訊數據並播放即可。

該腳本將附加到事件系統。 附加管理不是本提示的主要主題,因此它是合適的。

對於音訊剪輯,設置要播放的音訊檔。 將聲音播放管理器 SoundPlayManager 設置為要附加到的物件。 由於我們正在附加到事件系統,因此我們將設置事件系統。

最後,分配給 OnClick 按鈕按兩下事件。

完成後運行遊戲。 默認情況下,最大同時播放次數設置為 2,因此請在播放兩個聲音時再次按下該按鈕,並確保第一個聲音消失。

這次創建的程式對每種聲音的播放次數有上限,因此即使您交織其他音效,聽起來也很自然。 但是,根據聲音的類型,2 的上限可能還不夠,因此能夠為每種聲音類型設置上限可能是個好主意。 好吧,我不知道是否有這樣的機會來分層聲音,但是......