تعارف کے ساتھ پس منظر کی موسیقی لوپ کریں

جب صفحے کی تازہ کاری :
صفحہ تخلیق تاریخ :

تصدیق کا ماحول

Windows
  • ونڈوز 11
یونٹی ایڈیٹر
  • 2021.3.3f1
ان پٹ سسٹم پیکیج
  • 1.3.0

اس ٹوٹکے کے لئے ضروری شرائط

مندرجہ ذیل ترتیبات اس ٹپ کی وضاحت کے لئے بنیاد کے طور پر پیشگی بنائی گئی ہیں۔

نمونے کے ساتھ شامل مواد کے بارے میں

بی جی ایم مندرجہ ذیل سائٹ سے لیا گیا ہے۔

تعارف کے ساتھ لوپ کی آڈیو فائل کے بارے میں

اس بار ، صرف معیاری یونٹی فنکشن ایک تعارف کے ساتھ لوپ ادا کرے گا ، لیکن یہ معیاری فنکشن کے طور پر حمایت نہیں کرتا ہے۔ سب سے پہلے ، آڈیو فائل کے طور پر انٹرو کے ساتھ لوپ کی وضاحتیں طے نہیں ہیں ، لہذا تخلیق کا طریقہ گیم فریم ورک پر منحصر ہے۔

اس بار ، ہم "انٹرو" حصے اور "لوپ" حصے کے لئے دو آڈیو فائلیں تیار کریں گے ، ایک بار تعارفی حصہ چلائیں گے ، اور لوپ کا حصہ بار بار چلائیں گے۔ لہذا، براہ کرم مندرجہ بالا دو فائلوں کو آڈیو فائلوں کے طور پر تیار کریں.

کچھ ڈسٹری بیوشن سائٹس اس پر غور کرتی ہیں اور آڈیو فائلوں کو پیشگی علیحدہ طور پر تقسیم کرتی ہیں۔ اگر نہیں تو ، آپ کو اسے صوتی ایڈیٹنگ ٹول کے ساتھ خود بنانے کی ضرورت ہے۔

اگر آپ فائل کو دو حصوں میں تقسیم کرنا چاہتے ہیں تو ، ہم آڈیو فائل کی مندرجہ ذیل شکل کی سفارش کرتے ہیں۔

  • اوگ وربس (.ogg)
  • ڈبلیو اے وی (.wav)

مزید معلومات کے لئے، سرکاری یونٹی دستاویزات دیکھیں.

تعارف کے ساتھ لوپنگ بیک گراؤنڈ میوزک بجانے کے بارے میں

ایک یو آئی بنائیں جو آپ کو نمونے کے طور پر پس منظر کی موسیقی چلانے ، روکنے اور روکنے کی اجازت دیتا ہے۔ اس میں عام پس منظر میوزک پلے بیک نمونے کی طرح ہی ترتیب ہے۔

اپنے منصوبے میں دو آڈیو فائلیں شامل کریں ، دو حصوں میں تقسیم کریں ، ایک تعارف اور ایک لوپ۔

اس بار ، ہم تعارف کے ساتھ لوپنگ بی جی ایم کھیلنے کے لئے اپنا پروگرام بنائیں گے۔ اسکرپٹ بنائیں اور اسے نام IntroLoopAudio دیں۔

اسکرپٹ اس طرح نظر آتا ہے: میں مندرجہ ذیل سائٹ پر کوڈ کا حوالہ دے رہا ہوں ، لیکن میں نے بہت سارے کوڈ شامل کیے کیونکہ یہ ویب جی ایل کے ساتھ اچھی طرح سے کام نہیں کرتا تھا اور میں تھوڑا سا زیادہ کنٹرول چاہتا تھا۔

[حوالہ] 【اتحاد 】انٹرو + لوپ پلے کو نافذ کریں - 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;
  }
}

چونکہ کوڈ لمبا ہے ، لہذا میں تفصیلات کو چھوڑ دوں گا ، لیکن میں نے تعارف اور لوپ AudioClip کو پیشگی سیٹ کیا ، جب آپ کھیلنا شروع کرتے ہیں تو ، پہلے تعارف کھیلیں۔ لوپس کے لئے ، تعارف ختم ہونے پر انہیں کھیلنے کے لئے شیڈول کریں۔ ایک بار جب لوپ چلنا شروع ہوجائے تو ، اسے بار بار چلائیں۔

اصل میں ، loop لوپس کے لئے ، یہ پراپرٹی کو سیٹ کرنے کے true لئے کافی تھا ، لیکن یہ ویب جی ایل میں مناسب طریقے سے کام نہیں کرتا تھا۔ AudioSource میں دو لوپ تیار کرتا ہوں اور انہیں کھیلنے کے لئے باری باری تبدیل کرتا ہوں۔ اگر آپ کو ویب جی ایل پر غور کرنے کی ضرورت نہیں ہے تو ، آپ اپنے کوڈ کو نصف میں کاٹ سکتے ہیں۔

اسکرپٹ بنانے کے بعد ، آپ اسے کسی آبجیکٹ سے منسلک کرتے ہیں۔ عام طور پر ، خالی شے بنانا اور اسے منسلک کرنا بہتر ہوسکتا ہے ، لیکن یہ مشکل ہے ، لہذا اسے ایونٹ سسٹم سے منسلک کریں۔

تعارف اور لوپ آئٹمز موجود ہیں ، لہذا آڈیو فائل کو بالترتیب چھوڑ یں اور سیٹ کریں۔

اس وقت، کسی خاص پروسیسنگ کی ضرورت نہیں ہے. جب میں بٹن پر کلک کرتا ہوں تو میں اس پر عمل کرنا چاہتا ہوں ، لہذا میں بٹن کے لئے اسکرپٹ (ButtonEvent) بناتا ہوں۔

اسکرپٹ اس طرح نظر آتا ہے:

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 انسپکٹر سے اور ہر بٹن کے لئے کارروائی شامل کریں.

اسکرپٹ ایونٹ سسٹم سے منسلک ہے۔ چونکہ آپ کو انٹرو لوپ آڈیو سیٹ کرنے کی ضرورت ہے ، لہذا ایونٹ سسٹم سیٹ کریں جس میں انٹرو لوپ آڈیو ہے۔

اب تین بٹنوں کے کلک واقعات کے لئے طریقے تفویض کریں۔

ایک بار جب سب کچھ سیٹ اپ ہوجائے تو ، کھیل چلائیں اور اسے کھیلنے کی کوشش کریں۔ جب پلے بیک اختتام تک ختم ہوتا ہے تو ، آپ دیکھ سکتے ہیں کہ یہ گانے کے وسط سے لوپ ہوتا ہے اور چلتا ہے۔ یقینا ، یہ فرض کرتا ہے کہ آڈیو ڈیٹا کو اچھی طرح سے تقسیم کیا گیا ہے اور لوپس کو اچھی طرح سے منسلک کیا گیا ہے۔

موجودہ مدت ظاہر کریں

یہاں سے بونس کے طور پر ،IntroLoopAudio ہم نے ایک پراپرٹی شامل کی ہے جو ہمیں موجودہ پلے بیک ٹائم حاصل کرنے کی اجازت دیتی ہے ، لہذا آئیے اسے ڈسپلے کریں۔

سب سے پہلے ، وقت ظاہر کرنے کے لئے متن رکھیں۔

اسکرپٹ بنائیں۔

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

متن میں ایک اسکرپٹ منسلک کریں اور انٹرولوپ آڈیو کے ساتھ ایونٹ سسٹم سیٹ کریں۔

اسے چلائیں اور دیکھیں کہ آیا موجودہ پلے بیک وقت ظاہر ہوتا ہے۔ اس کے علاوہ ، لوپ کرتے وقت ، یہ چیک کرنے کی کوشش کریں کہ آیا وقت لوپ پوائنٹ پر واپس آتا ہے یا نہیں۔