Loop taustamuusika koos sissejuhatusega

Lehekülg uuendatud :
Lehe loomise kuupäev :

Kontrollimise keskkond

Windows
  • Windows 11
Ühtsuse toimetaja
  • 2021.3.3f1
Sisendsüsteemi pakett
  • 1.3.0

Selle näpunäite eeltingimused

Selle vihje kirjeldamise eelduseks on eelnevalt tehtud järgmised sätted.

Prooviga kaasas oleva materjali kohta

BGM on laenatud järgmiselt saidilt.

Silmuse helifaili kohta sissejuhatusega

Seekord mängib sissejuhatusega silmust ainult standardne Unity funktsioon, kuid seda ei toetata standardfunktsioonina. Esiteks ei ole intro kui helifailiga silmuse spetsifikatsioonid fikseeritud, seega erineb loomise meetod sõltuvalt mängu raamistikust.

Seekord valmistame ette kaks helifaili "intro" ja "loop" osa jaoks, mängime intro osa üks kord ja mängime silmuse osa korduvalt. Seetõttu valmistage ülaltoodud kaks faili helifailidena ette.

Mõned levitamissaidid kaaluvad seda ja levitavad helifaile eraldi eelnevalt. Kui ei, siis peate selle ise hääle redigeerimise tööriistaga tegema.

Kui soovite faili kaheks jagada, soovitame helifaili järgmist vormingut.

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

Lisateabe saamiseks vaadake Unity ametlikku dokumentatsiooni.

Teave silmuskudumise taustamuusika esitamise kohta sissejuhatusega

Looge kasutajaliides, mis võimaldab teil taustamuusikat näidisena esitada, peatada ja peatada. Sellel on sama paigutus kui tavalisel taustamuusika taasesituse näidisel.

Lisage oma projektile kaks helifaili, mis on jagatud kaheks osaks, sissejuhatuseks ja tsükliks.

Seekord loome oma programmi, et mängida silmuskuduvat BGM-i koos sissejuhatusega. Looge skript ja jätke selle nimi IntroLoopAudio .

Skript näeb välja selline: Viitan järgmise saidi koodile, kuid lisasin palju koodi, kuna see ei töötanud WebGL-iga hästi ja tahtsin veidi rohkem kontrolli.

[Viide] 【Ühtsus】Rakendage sissejuhatus + silmusmäng - 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;
  }
}

Kuna kood on pikk, jätan üksikasjad välja, kuid määran sissejuhatuse ja silmuse AudioClip ette, Kui hakkate mängima, mängige kõigepealt sissejuhatust. Silmuste puhul ajastage need mängima, kui sissejuhatus lõpeb. Kui silmus hakkab mängima, mängige seda korduvalt.

Algselt loop piisas silmuste jaoks vara seadmisest true , kuid see ei töötanud WebGL-is korralikult. AudioSource Valmistan ette kaks silmust ja vahetan need vaheldumisi mängimiseks. Kui te ei pea WebGL-i kaaluma, saate oma koodi pooleks lõigata.

Pärast skripti loomist manustate selle objektile. Tavaliselt võib olla parem luua tühi objekt ja lisada see, kuid see on tülikas, nii et kinnitage see EventSystemile.

Seal on sissejuhatuse ja silmuse üksused, nii et kukutage ja seadke helifail vastavalt.

Sel hetkel ei ole vaja spetsiaalset töötlemist. Ma tahan seda töödelda, kui klõpsan nuppu, nii et ma loon nupule skripti (ButtonEvent).

Skript näeb välja selline:

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 inspektorilt ja lisage iga nupu jaoks toimingud.

Skript on lisatud EventSystemile. Kuna peate seadistama Intro Loop Audio, määrake EventSystem, millel on Intro Loop Audio.

Nüüd määrake meetodid kolme nupu klõpsamissündmustele.

Kui kõik on seadistatud, käivitage mäng ja proovige seda mängida. Kui taasesitus lõpeb lõpuni, näete, et see silmustab loo keskelt ja mängib. Loomulikult eeldab see, et heliandmed on korralikult jagatud ja silmused on korralikult ühendatud.

Praeguse kestuse kuvamine

Boonusena oleme siit lisanud omaduse, mis võimaldab meil praeguse taasesitusaja sisse saada,IntroLoopAudio nii et kuvame selle.

Esmalt asetage tekst aja kuvamiseks.

Skripti loomine.

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

Manustage tekstile skript ja seadke EventSystem IntroLoopAudio abil.

Käivitage see ja vaadake, kas kuvatakse praegune taasesituse aeg. Samuti proovige silmuskudumisel kontrollida, kas aeg naaseb silmuspunkti.