Mengawal bilangan kesan bunyi serentak yang dimainkan

Laman dikemaskini :
Tarikh penciptaan halaman :

Persekitaran pengesahan

Windows
  • Windows 11
Penyunting Perpaduan
  • 2021.3.3F1
Pakej Sistem Input
  • 1.3.0

Prasyarat untuk petua ini

Tetapan berikut telah dibuat terlebih dahulu sebagai premis untuk penerangan petua ini.

Mengenai bahan yang disertakan dengan sampel

Kesan bunyi dipinjam dari laman web berikut.

Perihal fail audio

Format fail audio berikut boleh dimainkan dengan ciri standard Unity: Sila sediakannya terlebih dahulu kerana ia akan digunakan dalam petua ini.

  • WAV (.wav)
  • OggVorbis (.ogg)
  • MPEG lapisan 3 (.mp3)

Untuk maklumat lanjut, lihat dokumentasi Unity rasmi.

Perihal had atas dan kelantangan main balik audio berbilang serentak

Dalam petua sebelumnya, AudioClip kini mungkin untuk memainkan berbilang suara dengan memainkannya semasa menyediakan AudioSource.PlayOneShot data audio dalam . Walau bagaimanapun, tiada had kepada bilangan permainan yang boleh dimainkan, jadi jika anda tidak mengehadkannya semasa permainan, banyak bunyi boleh dimainkan dan kelantangan yang kuat boleh dimainkan.

Di sini saya ingin membuat program saya sendiri dan mengawal bilangan kesan bunyi yang boleh dimainkan pada masa yang sama.

Buat sampel

Kali ini, kesan bunyi akan dimainkan setiap kali anda mengklik butang, jadi buat UI seperti yang ditunjukkan dalam gambar. Butirannya sesuai dan baik.

Lepaskan dan tambah fail audio yang ingin anda mainkan ke dalam projek anda.

Sehingga kali terakhir, fungsi AudioSource standard telah ditambahkan pada hierarki, Kali ini, kami akan menambah skrip kerana kami akan meletakkan kawalan kami sendiri. SoundPlayManager Tinggalkan nama sebagai .

Buat skrip seperti berikut:

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

Oleh kerana skripnya panjang, penjelasan terperinci ditinggalkan, tetapi ia mempunyai fungsi berikut.

  • AudioClip Anda boleh memainkan audio dengan lulus
  • Apabila jenis audio yang sama dimainkan di bahagian atas satu sama lain, jika anda cuba memainkan lebih daripada bilangan suara tertentu, data main balik lama berhenti (nilai awal adalah sehingga 2 main balik).
  • Main balik bertindih pada bingkai yang sama tidak dibenarkan

Ini menghalang kelantangan daripada meningkat apabila audio yang sama dimainkan secara back-to-back. Dari segi fungsi, hanya minimum yang disertakan, jadi sila tambahkannya jika anda memerlukannya.

Skrip dilampirkan pada EventSystem.

Seterusnya, buat skrip untuk butang.

Buat skrip seperti berikut:

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

Proses main balik dilakukan oleh SoundPlayManager diri sendiri, jadi dalam acara butang, hanya lulus data audio dan mainkannya.

Skrip dilampirkan pada EventSystem. Lampirkan pengurusan bukan topik utama Petua ini, jadi sesuai.

Untuk klip audio, tetapkan fail audio untuk dimainkan. Setkan Pengurus Main Bunyi kepada objek yang SoundPlayManager anda lampirkan. Oleh kerana kami melampirkan kepada EventSystem, kami akan menetapkan EventSystem.

Akhirnya, berikan kepada butang klik OnClick peristiwa.

Jalankan permainan apabila anda selesai. Secara lalai, bilangan maksimum permainan serentak ditetapkan kepada 2, jadi sila klik butang sekali lagi semasa dua bunyi dimainkan dan pastikan bunyi pertama hilang.

Program yang dibuat kali ini mempunyai had atas bilangan masa main balik untuk setiap jenis bunyi, jadi ia kedengaran semula jadi walaupun anda mengaitkan kesan bunyi lain. Walau bagaimanapun, bergantung pada jenis bunyi, had atas 2 mungkin tidak mencukupi, jadi mungkin idea yang baik untuk dapat menetapkan had atas untuk setiap jenis bunyi. Baiklah, saya tidak tahu sama ada terdapat peluang untuk melapisi bunyi, tetapi ...