AudioClip:
AudioSource:
AudioListener:
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 ObjectPool objectPool;
private AudioSource musicAudioSource; // 실제로 오디오를 출력할 애
public AudioClip musicClip; // 실제 음원
private void Awake()
{
instance = this;
musicAudioSource = GetComponent<AudioSource>();
musicAudioSource.volume = musicVolume;
musicAudioSource.loop = true;
objectPool = GetComponent<ObjectPool>();
}
private void Start()
{
ChangeBackGroundMusic(musicClip); // 음악 재생
}
public static void ChangeBackGroundMusic(AudioClip music)
{
// ChangeBackGroundMusic가 static으로 선언(static method)되어 있기 때문에 static 변수만 사용할 수 있다.
// 정적 변수 instance를 통해서만 변수를 가져올 수 있기 때문에 instance. 을 사용했다.
instance.musicAudioSource.Stop();
instance.musicAudioSource.clip = music;
instance.musicAudioSource.Play();
}
public static void PlayClip(AudioClip clip)
{
GameObject obj = instance.objectPool.SpawnFromPool("SoundSource");
obj.SetActive(true);
SoundSource soundSource = obj.GetComponent<SoundSource>();
soundSource.Play(clip, instance.soundEffectVolume, instance.soundEffectPitchVariance);
}
}
public class SoundSource : MonoBehaviour
{
private AudioSource _audioSource;
// Play(재생할 AudioClip, 재생할 볼륨, 재생할 Pitch)
public void Play(AudioClip clip, float soundEffectVolume, float soundEffectPitchVariance)
{
if (_audioSource == null)
_audioSource = GetComponent<AudioSource>();
// 클립이 종료된 후 2초 안에 다시 클립이 재생될 경우 -> 밑의 Disable을 시키는 Invoke가 아직 실행 중일 경우 Cancel 시킨다.
CancelInvoke();
// 오디오 클립 초기화 -> 재사용하기 위해 매번 초기화를 해준다.
_audioSource.clip = clip;
_audioSource.volume = soundEffectVolume;
_audioSource.Play();
_audioSource.pitch = 1f + Random.Range(-soundEffectPitchVariance, soundEffectPitchVariance);
Invoke("Disable", clip.length + 2); // 클립 재생 이후 클립 종료 시키기. -> 클립의 길이 + 2초 만큼 기다렸다가 재생
}
public void Disable()
{
_audioSource.Stop();
gameObject.SetActive(false); // 오디오 클립을 disable 시킴
}
}
GameManager 밑에 SoundManager를 만들어 준다.
그리고 SounderManager.cs와 object pool을 넣어준다.
Create Empty → SoundSource 만들기
Audio Source 컴포넌트 추가, Play on Awake 꺼주기
SoundSource 스크립트 추가해주기
SoundManager의 object pool에 Pools 추가해주기
SoundManager에 Audio Source 추가해주기
TopDownShooting.cs로 와서 코드를 수정하자.
// TopDownShooting.cs
...
public AudioClip shootingClip;
...
private void CreateProjectile(RangedAttackData rangedAttackData, float angle)
{
// _projectileManager.ShootBullet(발사 위치, 발사 회전 각, 공격 정보)
_projectileManager.ShootBullet(
projectileSpawnPosition.position,
RotateVector2(_aimDirection, angle),
rangedAttackData);
// 발사체 생성 시 소리 출력하기
if (shootingClip)
{
SoundManager.PlayClip(shootingClip);
}
}
HealthSystem.cs에서 코드를 수정하자!
// HealthSystem.cs
...
public AudioClip damageClip;
...
public bool ChangeHealth(float change)
{
...
OnDamage?.Invoke(); // 음수라면, 데미지!
if (damageClip)
{
SoundManager.PlayClip(damageClip);
}
}
...