AudioClip은 Unity에서 사운드 파일을 저장하는 타입이다.
AudioSource 컴포넌트는 사운드를 재생하는데 사용된다. AudioClip을 연결하여 사운드를 재생한다.
또한 볼륨 설정, 사운드 반복 재생 등의 다양한 설정을 할 수 있다.
AudioListener 컴포넌트는 사운드를 듣기 위해 무조건 필요하고, 보통 MainCamera에 붙어있다.
게임 내에 하나의 컴포넌트만 존재해야 한다.
using UnityEngine;
public class AudioManager : Singleton<AudioManager>
{
public AudioClip backgroundMusic;
private AudioSource _audioSource;
void Start()
{
_audioSource = gameObject.AddComponent<AudioSource>();
_audioSource.loop = true;
PlayBackgroundMusic();
}
public void PlayBackgroundMusic()
{
if (backgroundMusic != null)
{
_audioSource.Stop();
_audioSource.clip = backgroundMusic;
_audioSource.Play();
}
else
{
Debug.LogWarning("[AudioManager] Background music is not set.");
}
}
public void PlaySound(AudioClip clip)
{
_audioSource.PlayOneShot(clip);
}
public void StopBackgroundMusic()
{
_audioSource.Stop();
}
}
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance
{
get
{
if (instance == null)
{
instance = (T)FindObjectOfType(typeof(T));
if (instance == null)
{
GameObject singletonObject = new GameObject();
instance = singletonObject.AddComponent<T>();
}
}
return _instance;
}
}
public void Awake()
{
DontDestroyOnLoad(instance);
}
}
이렇게 싱글톤 패턴의 AudioManager를 작성할 수 있다.
PlaySound 메서드를 통해 순간순간 AudioClip을 재생할 수 있다.
만약 이를 오브젝트 풀 패턴으로 작성하고 싶다면 오브젝트를 만들고
이를 통해 AudioClip을 재생하고 재활용하면 된다.
using UnityEngine;
public class SoundManager : MonoBehaviour
{
public static SoundManager instance;
[SerializeField][Range(0f, 1f)] private float soundEffectVolume;
[SerializeField][Range(0f, 1f)] private float soundEffectPitchVariance;
[SerializeField][Range(0f, 1f)] private float musicVolume;
private AudioSource musicAudioSource;
public AudioClip musicClip;
private void Awake()
{
instance = this;
musicAudioSource = GetComponent<AudioSource>();
musicAudioSource.volume = musicVolume;
musicAudioSource.loop = true;
}
private void Start()
{
ChangeBackgroundMusic(musicClip);
}
private void ChangeBackgroundMusic(AudioClip musicClip)
{
instance.musicAudioSource.Stop();
instance.musicAudioSource.clip = musicClip;
instance.musicAudioSource.Play();
}
public static void PlayClip(AudioClip clip)
{
GameObject obj = GameManager.Instance.ObjectPool.SpawnFromPool("SoundSource");
obj.SetActive(true);
SoundSource soundSource = obj.GetComponent<SoundSource>();
soundSource.Play(clip, instance.soundEffectVolume, instance.soundEffectPitchVariance);
}
}
using UnityEngine;
public class SoundSource : MonoBehaviour
{
private AudioSource audioSource;
public void Play(AudioClip clip, float soundEffectVolume, float soundEffectPitchVariance)
{
if(audioSource == null)
audioSource = GetComponent<AudioSource>();
CancelInvoke();
audioSource.clip = clip;
audioSource.volume = soundEffectVolume;
audioSource.pitch = 1f + Random.Range(-soundEffectPitchVariance, soundEffectPitchVariance);
audioSource.Play();
Invoke("Disable", clip.length + 2);
}
public void Disable()
{
audioSource.Stop();
gameObject.SetActive(false);
}
}
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool : MonoBehaviour
{
[System.Serializable]
public class Pool
{
public string tag;
public GameObject prefab;
public int size;
}
public List<Pool> Pools;
public Dictionary<string, Queue<GameObject>> PoolDictionary;
private void Awake()
{
PoolDictionary = new Dictionary<string, Queue<GameObject>>();
foreach (var pool in Pools)
{
Queue<GameObject> objectPool = new Queue<GameObject>();
for (int i = 0; i < pool.size; i++)
{
GameObject obj = Instantiate(pool.prefab);
obj.SetActive(false);
objectPool.Enqueue(obj);
}
PoolDictionary.Add(pool.tag, objectPool);
}
}
public GameObject SpawnFromPool(string tag)
{
if (!PoolDictionary.ContainsKey(tag))
return null;
GameObject obj = PoolDictionary[tag].Dequeue();
PoolDictionary[tag].Enqueue(obj);
return obj;
}
}
using UnityEngine;
public class GameManager : MonoBehaviour
{
public static GameManager Instance;
public ObjectPool ObjectPool { get; private set; }
private void Awake()
{
if(Instance != null) Destroy(gameObject);
Instance = this;
ObjectPool = GetComponent<ObjectPool>();
}
}
'TIL' 카테고리의 다른 글
[ 24.06.14 ] 내일배움캠프 TIL - Application Quit (0) | 2024.06.14 |
---|---|
[ 24.06.13 ] 내일배움캠프 TIL - UGUI, Coroutine (0) | 2024.06.13 |
[ 24.06.10 ] 내일배움캠프 38일차 TIL - Prefab 로딩 (0) | 2024.06.10 |
[ 24.05.27 ] 내일배움캠프 29일차 TIL - 카메라 회전 (0) | 2024.05.28 |
[ 24.05.24 ] 내일배움캠프 28일차 TIL - SkyBox, RayCast (0) | 2024.05.24 |