UNITY/Script

[UNITY C#] Intro Loopable AudioSource 구현

HYEOKJUN 2024. 9. 26. 14:46
반응형


https://johnleonardfrench.com/ultimate-guide-to-playscheduled-in-unity/

 

How to Queue Audio Clips in Unity (the Ultimate Guide to PlayScheduled) - John Leonard French

Learn How to queue up Audio Clips (seamlessly), make dynamic music & beat-match audio in my ultimate guide to PlayScheduled in Unity.

johnleonardfrench.com


Intro Loopable Music

Unity에서는 [AudioSource Component]Loop 옵션을 체크하여 사운드 파일이 종료되었을 때 처음으로 돌아가 다시 재생시킬 수 있는 기능이 있습니다.
따라서 Loopable Music(반복 가능 음악)을 재생시키기 적합한 환경이라고 할 수 있습니다.
하지만 Intro가 있는 Loopable Music, 즉 Intro Loopable Music의 경우에는
Intro부분 Loop부분 두 개의 사운드 파일로 나누어

1. AudioSoruce에 Intro.wav를 재생시킵니다.
2. Intro.wav가 끝남과 동시에 Loop 항목을 체크하고 Loop.wav를 재생시킵니다.

다음과 같은 과정을 거쳐야 합니다.


잘못된 구현 방법

위 과정은 구현하기에 간단해 보입니다. 단순히 생각하여 구현해보면

using System.Collections;
using UnityEngine;

public class IntroLoopableAudioSource : MonoBehaviour
{
	[SerializeField] AudioSource audioSource;

	public void Play(AudioClip audioClip_intro, AudioClip audioClip_loop) {
		audioSource.clip = audioClip_intro;
		audioSource.loop = false;
		audioSource.Play();
		StartCoroutine(PlayLoop());

		IEnumerator PlayLoop() {
			yield return new WaitForSeconds(audioClip_intro.length);

			audioSource.clip = audioClip_loop;
			audioSource.loop = true;
			audioSource.Play();
		}
	}
}

다음과 같이 작성할 수 있습니다.

하지만 특히 시스템 성능이 낮은 경우, 사운드 파일의 크기가 큰 경우 사운드가 Intro에서 Loop로 전환될 때 바로 전환되지 않고 잠시 끊기는 현상이 일어나기도 합니다.
이 현상은 플레이어의 몰입 방해, 불쾌한 경험을 줄 수 있으므로 끊기지 않고 자연스러운 전환이 일어나도록 해야 합니다.


기본 설정

GameObject를 생성하여 2개의 [AudioSource Component]추가하고 Play On Awake 옵션해제합니다.


Scripting

 

IntroLoopableAudioClip.cs

using System;
using UnityEngine;

[Serializable]
public class IntroLoopableAudioClip
{
    public AudioClip audioClip_intro, audioClip_loop;
}

IntroLoopableAudioSource.cs

더보기
더보기
using UnityEngine;

public class IntroLoopableAudioSource : MonoBehaviour
{
	[SerializeField] AudioSource[] audioSources;

	public void Play(IntroLoopableAudioClip introLoopableAudioClip) {
		Play(introLoopableAudioClip.audioClip_intro, introLoopableAudioClip.audioClip_loop);
	}

	public void Play(AudioClip audioClip_intro, AudioClip audioClip_loop) {
		audioSources[0].clip = audioClip_intro;
		audioSources[0].loop = false;
		audioSources[1].clip = audioClip_loop;
		audioSources[1].loop = true;

		double startTime = AudioSettings.dspTime; 

		audioSources[0].PlayScheduled(startTime);
		audioSources[1].PlayScheduled(startTime + audioClip_intro.length);
	}

	public void Pause() {
		AudioListener.pause = true;
	}
	public void UnPause() {
		AudioListener.pause = false;
	}
 }

AudioSource의 PlayScheduled 메서드dspTime을 이용하여 Intro.wav가 끝나는 정확한 시간에 Loop.wav를 재생하도록 합니다.

다음과 같이 스크립트를 추가하여 AudioSource모두 할당합니다.

PlayScheduled 메서드를 사용하면 AudioSource의 Pause, UnPause 메서드가 제대로 작동하지 않습니다.

(제 시간에 Loop.wav가 재생되지 않는 등)

AudioListener.pause = true;

따라서 AudioListener의 pause 값을 조정하여 재생을 정지합니다.

AudioListener.pause는 모든 Audio를 중지시키므로 일시정지 시에도 계속 재생되길 원한다면
AudioSource의 ignoreListenerPause를 true로 설정하여 AudioListener의 일시정지를 무시하도록 합니다.
audioSource.ignoreListenerPause = true;​
반응형