Muzik latar belakang gelung dengan pengenalan

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

BGM dipinjam dari laman web berikut.

Mengenai fail audio gelung dengan pengenalan

Kali ini, hanya fungsi Unity standard akan memainkan gelung dengan intro, tetapi ini tidak disokong sebagai fungsi standard. Di tempat pertama, spesifikasi gelung dengan intro sebagai fail audio tidak tetap, jadi kaedah penciptaan berbeza bergantung pada rangka kerja permainan.

Kali ini, kami akan menyediakan dua fail audio untuk bahagian "pengenalan" dan bahagian "gelung", memainkan bahagian intro sekali, dan memainkan bahagian gelung berulang kali. Oleh itu, sila sediakan dua fail di atas sebagai fail audio.

Sesetengah tapak pengedaran mempertimbangkan ini dan mengedarkan fail audio secara berasingan terlebih dahulu. Jika tidak, anda perlu membuatnya sendiri dengan alat penyuntingan suara.

Jika anda ingin membahagikan fail kepada dua, kami mengesyorkan format fail audio berikut.

  • OggVorbis (.ogg)
  • WAV (.wav)

Untuk maklumat lanjut, lihat dokumentasi Unity rasmi.

Mengenai memainkan muzik latar belakang gelung dengan pengenalan

Buat UI yang membolehkan anda bermain, menjeda dan menghentikan muzik latar belakang sebagai sampel. Ia mempunyai susun atur yang sama seperti sampel main balik muzik latar belakang biasa.

Tambah dua fail audio pada projek anda, dibahagikan kepada dua bahagian, pengenalan dan gelung.

Kali ini, kami akan mencipta program kami sendiri untuk memainkan BGM gelung dengan intro. Buat skrip dan biarkan ia dinamakan IntroLoopAudio .

Skrip kelihatan seperti ini: Saya merujuk kepada kod di laman web berikut, tetapi saya menambah banyak kod kerana ia tidak berfungsi dengan baik dengan WebGL dan saya mahukan sedikit kawalan.

[Rujukan] 【Perpaduan】Melaksanakan Intro + Permainan Gelung - 7080 + 1

using UnityEngine;

/// <summary>
/// イントロ付きループ BGM を制御するクラスです。
/// </summary>
/// <remarks>
/// WebGL では PlayScheduled で再生するとループしないのでその対応を入れている。
/// WebGL では2つの AudioSource を交互に再生。
/// </remarks>
public class IntroLoopAudio : MonoBehaviour
{
  /// <summary>BGM のイントロ部分の音声データ。</summary>
  [SerializeField] private AudioClip AudioClipIntro;

  /// <summary>BGM のループ部分の音声データ。</summary>
  [SerializeField] private AudioClip AudioClipLoop;

  /// <summary>BGM のイントロ部分の AudioSource。</summary>
  private AudioSource _introAudioSource;

  /// <summary>BGM のループ部分の AudioSource。</summary>
  private AudioSource[] _loopAudioSources = new AudioSource[2];

  /// <summary>一時停止中かどうか。</summary>
  private bool _isPause;

  /// <summary>現在の再生するループ部分のインデックス。</summary>
  private int _nowPlayIndex = 0;

  /// <summary>ループ部分に使用する AudioSource の数。</summary>
  private int _loopSourceCount = 0;

  /// <summary>再生中であるかどうか。一時停止、非アクティブの場合は false を返す。</summary>
  private bool IsPlaying
    => (_introAudioSource.isPlaying || _introAudioSource.time > 0)
      || (_loopAudioSources[0].isPlaying || _loopAudioSources[0].time > 0)
      || (_loopAudioSources[1] != null && (_loopAudioSources[1].isPlaying || _loopAudioSources[1].time > 0));

  /// <summary>現在アクティブで再生しているループ側の AudioSource。</summary>
  private AudioSource LoopAudioSourceActive
    => _loopAudioSources[1] != null && _loopAudioSources[1].time > 0 ? _loopAudioSources[1] : _loopAudioSources[0];

  /// <summary>現在の再生時間 (s)。</summary>
  public float time
    => _introAudioSource == null ? 0
      : _introAudioSource.time > 0 ? _introAudioSource.time
      : LoopAudioSourceActive.time > 0 ? AudioClipIntro.length + LoopAudioSourceActive.time
      : 0;


  void Start()
  {
    _loopSourceCount = 2;   // WebGL でなければ 1 でもよい

    // AudioSource を自身に追加
    _introAudioSource = gameObject.AddComponent<AudioSource>();
    _loopAudioSources[0] = gameObject.AddComponent<AudioSource>();
    if (_loopSourceCount >= 2)
    {
      _loopAudioSources[1] = gameObject.AddComponent<AudioSource>();
    }

    _introAudioSource.clip = AudioClipIntro;
    _introAudioSource.loop = false;
    _introAudioSource.playOnAwake = false;

    _loopAudioSources[0].clip = AudioClipLoop;
    _loopAudioSources[0].loop = _loopSourceCount == 1;
    _loopAudioSources[0].playOnAwake = false;
    if (_loopAudioSources[1] != null)
    {
      _loopAudioSources[1].clip = AudioClipLoop;
      _loopAudioSources[1].loop = false;
      _loopAudioSources[1].playOnAwake = false;
    }
  }

  void Update()
  {
    // WebGL のためのループ切り替え処理
    if (_loopSourceCount >= 2)
    {
      // 終了する1秒前から次の再生のスケジュールを登録する
      if (_nowPlayIndex == 0 && _loopAudioSources[0].time >= AudioClipLoop.length - 1)
      {
        _loopAudioSources[1].PlayScheduled(AudioSettings.dspTime + (AudioClipLoop.length - _loopAudioSources[0].time));
        _nowPlayIndex = 1;
      }
      else if (_nowPlayIndex == 1 && _loopAudioSources[1].time >= AudioClipLoop.length - 1)
      {
        _loopAudioSources[0].PlayScheduled(AudioSettings.dspTime + (AudioClipLoop.length - _loopAudioSources[1].time));
        _nowPlayIndex = 0;
      }
    }
  }

  public void Play()
  {
    // クリップが設定されていない場合は何もしない
    if (_introAudioSource == null || _loopAudioSources == null) return;

    // Pause 中は isPlaying は false
    // 標準機能だけでは一時停止中か判別不可能
    if (_isPause)
    {
      _introAudioSource.UnPause();
      if (_introAudioSource.isPlaying)
      {
        // イントロ中ならループ開始時間を残り時間で再設定
        _loopAudioSources[0].Stop();
        _loopAudioSources[0].PlayScheduled(AudioSettings.dspTime + AudioClipIntro.length - _introAudioSource.time);
      }
      else
      {
        if (_loopSourceCount >= 2)
        {
          // WebGL の場合は切り替え処理を実行
          if (_loopAudioSources[0].time > 0)
          {
            _loopAudioSources[0].UnPause();
            if (_loopAudioSources[0].time >= AudioClipLoop.length - 1)
            {
              _loopAudioSources[1].Stop();
              _loopAudioSources[1].PlayScheduled(AudioSettings.dspTime + (AudioClipLoop.length - _loopAudioSources[0].time));
              _nowPlayIndex = 1;
            }
          }
          else
          {
            _loopAudioSources[1].UnPause();
            if (_loopAudioSources[1].time >= AudioClipLoop.length - 1)
            {
              _loopAudioSources[0].Stop();
              _loopAudioSources[0].PlayScheduled(AudioSettings.dspTime + (AudioClipLoop.length - _loopAudioSources[0].time));
              _nowPlayIndex = 0;
            }
          }
        }
        else
        {
          // WebGL 以外は UnPause するだけ
          _loopAudioSources[0].UnPause();
        }
      }
    }
    else if (IsPlaying == false)
    {
      // 最初から再生
      Stop();
      _introAudioSource.Play();

      // イントロの時間が経過した後に再生できるようにする
      // 設定する時間はゲーム刑か時間での設定となる
      _loopAudioSources[0].PlayScheduled(AudioSettings.dspTime + AudioClipIntro.length);
    }

    _isPause = false;
  }

  /// <summary>BGM を一時停止します。</summary>
  public void Pause()
  {
    if (_introAudioSource == null || _loopAudioSources == null) return;

    _introAudioSource.Pause();
    _loopAudioSources[0].Pause();
    if (_loopAudioSources[1] != null) _loopAudioSources[1].Pause();

    _isPause = true;
  }

  /// <summary>BGM を停止します。</summary>
  public void Stop()
  {
    if (_introAudioSource == null || _loopAudioSources == null) return;

    _introAudioSource.Stop();
    _loopAudioSources[0].Stop();
    if (_loopAudioSources[1] != null) _loopAudioSources[1].Stop();

    _isPause = false;
  }
}

Oleh kerana kod itu panjang, saya akan meninggalkan butirannya, tetapi saya menetapkan intro dan gelung AudioClip terlebih dahulu, Apabila anda mula bermain, mainkan intro terlebih dahulu. Untuk gelung, jadualkannya untuk dimainkan apabila intro berakhir. Sebaik sahaja gelung mula bermain, mainkannya berulang kali.

Pada asalnya, untuk gelung, sudah cukup untuk menetapkan harta itu true kepada , loop tetapi ia tidak berfungsi dengan betul di WebGL. AudioSource Saya menyediakan dua gelung dan menukarnya secara bergilir-gilir untuk bermain. Jika anda tidak perlu mempertimbangkan WebGL, anda boleh memotong kod anda separuh.

Selepas anda mencipta skrip, anda melampirkannya pada objek. Biasanya, mungkin lebih baik untuk mencipta objek kosong dan melampirkannya, tetapi menyusahkan, jadi pasangkannya ke EventSystem.

Terdapat item pengenalan dan gelung, jadi jatuhkan dan tetapkan fail audio masing-masing.

Pada ketika ini, tiada pemprosesan khas diperlukan. Saya mahu memprosesnya apabila saya mengklik butang, jadi saya membuat skrip (ButtonEvent) untuk butang.

Skrip kelihatan seperti ini:

using UnityEngine;

public class ButtonEvent : MonoBehaviour
{
  [SerializeField] private IntroLoopAudio IntroLoopAudio;

  public void OnClickPlay()
  {
    IntroLoopAudio.Play();
  }
  public void OnClickPause()
  {
    IntroLoopAudio.Pause();
  }
  public void OnClickStop()
  {
    IntroLoopAudio.Stop();
  }
}

IntroLoopAudio dari pemeriksa dan tambah tindakan untuk setiap butang.

Skrip dilampirkan pada EventSystem. Memandangkan anda perlu mengesetkan Audio Gelung Pengenalan, setkan Sistem Acara yang mempunyai Audio Gelung Pengenalan.

Sekarang berikan kaedah kepada peristiwa klik tiga butang.

Sebaik sahaja semuanya disediakan, jalankan permainan dan cuba mainkannya. Apabila main balik berakhir hingga akhir, anda dapat melihat bahawa ia gelung dari tengah lagu dan drama. Sudah tentu, ini mengandaikan bahawa data audio dibahagikan dengan kemas dan gelung disambungkan dengan kemas.

Paparkan tempoh semasa

Sebagai bonus dari sini,IntroLoopAudio kami telah menambah hartanah yang membolehkan kami mendapatkan masa main balik semasa , jadi mari paparkannya.

Mula-mula, letakkan teks untuk memaparkan masa.

Buat skrip.

using UnityEngine;
using UnityEngine;
using UnityEngine.UI;

public class TextEvent : MonoBehaviour
{
  [SerializeField] private IntroLoopAudio IntroLoopAudio;

  private Text _text;

  // Start is called before the first frame update
  void Start()
  {
    _text = GetComponent<Text>();
  }

  // Update is called once per frame
  void Update()
  {
    _text.text = $"AudioPlayTime : {IntroLoopAudio.time}";
  }
}

Lampirkan skrip pada teks dan tetapkan EventSystem dengan IntroLoopAudio.

Jalankannya dan lihat sama ada masa main balik semasa dipaparkan. Juga, apabila gelung, cuba semak sama ada masa kembali ke titik gelung.