วนเพลงประกอบด้วยบทนํา
สภาพแวดล้อมการตรวจสอบ
- หน้าต่าง
-
- หน้าต่าง 11
- บรรณาธิการ Unity
-
- ปี 2021.3.3f1
- แพ็คเกจระบบอินพุต
-
- 1.3.0
ข้อกําหนดเบื้องต้นสําหรับเคล็ดลับนี้
การตั้งค่าต่อไปนี้ได้ทําไว้ล่วงหน้าเพื่อเป็นหลักฐานสําหรับคําอธิบายของเคล็ดลับนี้
เกี่ยวกับวัสดุที่มาพร้อมกับตัวอย่าง
BGM ยืมจากเว็บไซต์ต่อไปนี้
เกี่ยวกับไฟล์เสียงของลูปพร้อมบทนํา
คราวนี้เฉพาะฟังก์ชัน Unity มาตรฐานเท่านั้นที่จะเล่นลูปพร้อมบทนํา แต่ไม่ได้รับการสนับสนุนเป็นฟังก์ชันมาตรฐาน ในตอนแรกข้อกําหนดของลูปที่มีบทนําเป็นไฟล์เสียงจะไม่ได้รับการแก้ไขดังนั้นวิธีการสร้างจึงแตกต่างกันไปขึ้นอยู่กับเฟรมเวิร์กเกม
คราวนี้เราจะเตรียมไฟล์เสียงสองไฟล์สําหรับส่วน "บทนํา" และส่วน "ลูป" เล่นส่วนบทนําหนึ่งครั้งและเล่นส่วนลูปซ้ํา ๆ ดังนั้นโปรดเตรียมไฟล์สองไฟล์ข้างต้นเป็นไฟล์เสียง
ไซต์การแจกจ่ายบางแห่งพิจารณาสิ่งนี้และแจกจ่ายไฟล์เสียงแยกต่างหากล่วงหน้า ถ้าไม่คุณต้องทําด้วยตัวเองด้วยเครื่องมือแก้ไขเสียง
หากคุณต้องการแยกไฟล์ออกเป็นสองไฟล์เราขอแนะนํารูปแบบต่อไปนี้ของไฟล์เสียง
- OggVorbis (.ogg)
- WAV (.wav)
สําหรับข้อมูลเพิ่มเติม โปรดดูเอกสาร Unity อย่างเป็นทางการ
เกี่ยวกับการเล่นเพลงประกอบแบบวนซ้ําด้วยบทนํา
สร้าง UI ที่ให้คุณเล่น หยุดชั่วคราว และหยุดเพลงประกอบเป็นตัวอย่างได้ มีเลย์เอาต์เหมือนกับตัวอย่างการเล่นเพลงประกอบปกติ
เพิ่มไฟล์เสียงสองไฟล์ลงในโครงการของคุณแบ่งออกเป็นสองส่วนบทนําและลูป
คราวนี้เราจะสร้างโปรแกรมของเราเองเพื่อเล่น BGM แบบวนซ้ําด้วยบทนํา
สร้างสคริปต์และปล่อยให้ชื่อ IntroLoopAudio
.
สคริปต์มีลักษณะดังนี้: ฉันหมายถึงรหัสในเว็บไซต์ต่อไปนี้ แต่ฉันเพิ่มโค้ดจํานวนมากเพราะมันทํางานได้ไม่ดีกับ WebGL และฉันต้องการการควบคุมเพิ่มเติมเล็กน้อย
[อ้างอิง] 【Unity】ใช้บทนํา + การเล่นวนซ้ํา - 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
คุณสมบัติเป็น แต่ทํางานไม่ถูกต้องใน WebGL
AudioSource
ฉันเตรียมสองลูปและสลับกันเล่น
หากคุณไม่จําเป็นต้องพิจารณา WebGL คุณสามารถลดโค้ดลงครึ่งหนึ่งได้
หลังจากที่คุณสร้างสคริปต์ คุณแนบสคริปต์นั้นกับวัตถุ โดยปกติมันอาจจะดีกว่าที่จะสร้างวัตถุที่ว่างเปล่าและแนบมัน แต่มันลําบากดังนั้นแนบไปกับ EventSystem
มีรายการแนะนําและลูปดังนั้นวางและตั้งค่าไฟล์เสียงตามลําดับ
ณ จุดนี้ไม่จําเป็นต้องมีการประมวลผลพิเศษ
ฉันต้องการประมวลผลเมื่อฉันคลิกปุ่มดังนั้นฉันจึงสร้างสคริปต์ (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
จากตัวตรวจสอบและเพิ่มการดําเนินการสําหรับแต่ละปุ่ม
สคริปต์ที่แนบมากับ EventSystem เนื่องจากคุณต้องตั้งค่า Intro Loop Audio ให้ตั้งค่า EventSystem ที่มี Intro Loop Audio
ตอนนี้กําหนดวิธีการให้กับเหตุการณ์การคลิกของปุ่มสามปุ่ม
เมื่อตั้งค่าทุกอย่างแล้วให้เรียกใช้เกมและลองเล่น เมื่อการเล่นสิ้นสุดลงคุณจะเห็นว่ามันวนซ้ําจากกลางเพลงและเล่น แน่นอนว่าสิ่งนี้ถือว่าข้อมูลเสียงถูกแบ่งออกอย่างเรียบร้อยและลูปเชื่อมต่ออย่างเรียบร้อย
แสดงระยะเวลาปัจจุบัน
เป็นโบนัสจากที่นี่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}";
}
}
แนบสคริปต์กับข้อความและตั้งค่า EventSystem ด้วย IntroLoopAudio
เรียกใช้และดูว่าเวลาเล่นปัจจุบันแสดงขึ้นหรือไม่ นอกจากนี้เมื่อวนซ้ําให้ลองตรวจสอบว่าเวลากลับไปที่จุดวนซ้ําหรือไม่