ควบคุมจํานวนเอฟเฟ็กต์เสียงที่เล่นพร้อมกัน

ปรับปรุงหน้า :
วันที่สร้างเพจ :

สภาพแวดล้อมการตรวจสอบ

หน้าต่าง
  • หน้าต่าง 11
บรรณาธิการ Unity
  • ปี 2021.3.3f1
แพ็คเกจระบบอินพุต
  • 1.3.0

ข้อกําหนดเบื้องต้นสําหรับเคล็ดลับนี้

การตั้งค่าต่อไปนี้ได้ทําไว้ล่วงหน้าเพื่อเป็นหลักฐานสําหรับคําอธิบายของเคล็ดลับนี้

เกี่ยวกับวัสดุที่มาพร้อมกับตัวอย่าง

เอฟเฟกต์เสียงยืมมาจากไซต์ต่อไปนี้

เกี่ยวกับไฟล์เสียง

รูปแบบไฟล์เสียงต่อไปนี้สามารถเล่นได้ด้วยคุณสมบัติมาตรฐานของ Unity: โปรดเตรียมล่วงหน้าเพราะจะใช้ในเคล็ดลับเหล่านี้

  • WAV (.wav)
  • OggVorbis (.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 ครั้ง)
  • ไม่อนุญาตให้เล่นภาพซ้อนทับกันในเฟรมเดียวกัน

วิธีนี้จะป้องกันไม่ให้ระดับเสียงเพิ่มขึ้นเมื่อเล่นเสียงเดียวกันแบบย้อนกลับ ในแง่ของการทํางานมีเพียงขั้นต่ําเท่านั้นที่รวมอยู่ด้วยดังนั้นโปรดเพิ่มหากคุณต้องการ

สคริปต์ที่แนบมากับ EventSystem

จากนั้นสร้างสคริปต์สําหรับปุ่ม

สร้างสคริปต์ดังนี้:

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 เองดังนั้นในเหตุการณ์ปุ่มเพียงแค่ส่งข้อมูลเสียงและเล่น

สคริปต์ที่แนบมากับ EventSystem การจัดการแนบไม่ใช่หัวข้อหลักของเคล็ดลับนี้ดังนั้นจึงเหมาะสม

สําหรับคลิปเสียง ให้ตั้งค่าไฟล์เสียงที่จะเล่น ตั้งค่า Sound Play Manager ไปที่ SoundPlayManager วัตถุที่คุณกําลังแนบอยู่ เนื่องจากเรากําลังแนบกับ EventSystem เราจะตั้งค่า EventSystem

สุดท้ายกําหนดให้กับ OnClick เหตุการณ์การคลิกปุ่ม

เรียกใช้เกมเมื่อคุณทําเสร็จแล้ว โดยค่าเริ่มต้นจํานวนการเล่นพร้อมกันสูงสุดจะถูกตั้งค่าเป็น 2 ดังนั้นโปรดคลิกปุ่มอีกครั้งในขณะที่เสียงสองเสียงกําลังเล่นและตรวจสอบให้แน่ใจว่าเสียงแรกหายไป

โปรแกรมที่สร้างขึ้นในครั้งนี้มีขีด จํากัด บนจํานวนครั้งในการเล่นสําหรับเสียงแต่ละประเภทดังนั้นจึงฟังดูเป็นธรรมชาติแม้ว่าคุณจะผสมผสานเอฟเฟกต์เสียงอื่น ๆ อย่างไรก็ตามขึ้นอยู่กับประเภทของเสียงขีด จํากัด บนของ 2 อาจไม่เพียงพอดังนั้นจึงอาจเป็นความคิดที่ดีที่จะสามารถตั้งค่าขีด จํากัด บนสําหรับเสียงแต่ละประเภทได้ ฉันไม่รู้ว่ามีโอกาสที่จะเลเยอร์เสียงหรือไม่ แต่ ...