Az egyidejűleg lejátszott hangeffektusok számának szabályozása

Oldal frissítve :
Oldal létrehozásának dátuma :

Ellenőrzési környezet

Windows
  • Windows 11 esetén
Unity-szerkesztő
  • 2021.3.3f1
Bemeneti rendszercsomag
  • 1.3.0

A tipp előfeltételei

A következő beállításokat előre elvégeztük a tipp leírásának előfeltételeként.

A mintához mellékelt anyagról

A hanghatásokat a következő webhelyekről kölcsönzik.

Hangfájlokról

A következő hangfájlformátumok játszhatók le a Unity szabványos funkcióival: Kérjük, készítse elő előre, mert ezekben a tippekben fogják használni.

  • WAV (.wav)
  • OggVorbis negyed (.ogg)
  • MPEG 3. réteg (.mp3)

További információért tekintse meg a Unity hivatalos dokumentációját.

Több egyidejű hanglejátszás felső korlátja és hangereje

Az előző tippekben most már több hangot is le lehet játszani lejátszással, AudioClip miközben hangadatokat készít AudioSource.PlayOneShot elő . A játszható játékok száma azonban nincs korlátozva, így ha nem korlátozza a játék során, sok hang játszható le, és hangos hangerő játszható le.

Itt szeretném létrehozni a saját programomat és szabályozni az egyszerre lejátszható hanghatások számát.

A minta létrehozása

Ezúttal a hangeffektus minden alkalommal lejátszásra kerül, amikor rákattint a gombra, ezért hozza létre a felhasználói felületet az ábrán látható módon. A részletek megfelelőek és jók.

Dobja el és adja hozzá a lejátszani kívánt hangfájlt a projekthez.

A legutóbbi alkalomig az standard funkciója AudioSource hozzá volt adva a hierarchiához, Ezúttal hozzáadunk egy szkriptet, mert saját irányítást biztosítunk. SoundPlayManager Hagyja meg a nevet .

Hozza létre a szkriptet az alábbiak szerint:

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

Mivel a szkript hosszú, a részletes magyarázat kimarad, de a következő funkciókkal rendelkezik.

  • AudioClip A hangot úgy játszhatja le, hogy elhalad
  • Ha ugyanazt a típusú hangot játssza le egymáson, ha egy bizonyos számnál több hangot próbál lejátszani, a régi lejátszási adatok leállnak (a kezdeti érték legfeljebb 2 lejátszás).
  • Az átfedésben lévő lejátszás ugyanazon a képkockán nem engedélyezett

Ez megakadályozza a hangerő növekedését, amikor ugyanazt a hangot egymás után játssza le. Ami a funkcionalitást illeti, csak a minimumot tartalmazza, ezért kérjük, adja hozzá, ha szüksége van rá.

A szkript az EventSystemhez van csatolva.

Ezután hozzon létre egy szkriptet a gombhoz.

Hozza létre a szkriptet az alábbiak szerint:

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

A lejátszási folyamatot a saját SoundPlayManager készítésű végzi, így a gombeseményen csak adja át az audio adatokat és játssza le.

A szkript az EventSystemhez van csatolva. A csatolási kezelés nem a fő témája ennek a tippnek, ezért helyénvaló.

A hangkliphez állítsa be a lejátszani kívánt hangfájlt. Állítsa be a Hanglejátszás-kezelőt arra az SoundPlayManager objektumra, amelyhez csatolni kívánja. Mivel az EventSystemhez kapcsolódunk, beállítjuk az EventSystem-et.

Végül rendelje hozzá a gombra kattintási OnClick eseményhez.

Futtassa a játékot, ha végzett. Alapértelmezés szerint az egyidejű lejátszások maximális száma 2-re van állítva, ezért kattintson ismét a gombra, miközben két hang szól, és győződjön meg arról, hogy az első hang eltűnik.

Az ezúttal létrehozott programnak felső korlátja van az egyes hangtípusok lejátszási idejének számára, így természetesnek hangzik, még akkor is, ha más hanghatásokat sző. A hang típusától függően azonban előfordulhat, hogy a 2-es felső határ nem elegendő, ezért jó ötlet lehet minden hangtípushoz felső határt beállítani. Nos, nem tudom, van-e ilyen lehetőség a hang rétegezésére, de ...