Unity 입문 TopDown Shooting - 사운드 컨트롤

Amberjack·2024년 1월 22일
0

Unity

목록 보기
19/44

🔊 사운드를 처리하는 주요 컴포넌트

AudioClip:

  • AudioClip은 사운드 파일을 Unity에서 사용할 수 있도록 하는 데이터 타입.
  • .wav, .mp3, .ogg 등 다양한 형식의 오디오 파일을 지원한다.

AudioSource:

  • AudioSource 컴포넌트는 사운드를 재생하는 데 사용된다.
  • AudioSource에 AudioClip을 연결하여 재생할 수 있다.
  • AudioSource는 3D 사운드 설정, 볼륨 조절, 사운드 반복 재생 등의 설정을 제공한다.

AudioListener:

  • AudioListener 컴포넌트는 사운드를 듣는 포인트를 나타낸다.
  • 일반적으로 주요 카메라에 AudioListener가 위치.
  • 게임에는 하나의 AudioListener만 있어야 함.

⌨️ SoundManager.cs

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

⌨️ SoundSource.cs

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 시킴
    }
}

🔈 SoundManager 만들기

GameManager 밑에 SoundManager를 만들어 준다.
그리고 SounderManager.cs와 object pool을 넣어준다.

🎵 SoundSource 만들기

Create Empty → SoundSource 만들기

Audio Source 컴포넌트 추가, Play on Awake 꺼주기

SoundSource 스크립트 추가해주기

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

...

🎵 AudioClip 넣어주기

플레이어에게 shootingClip을 넣어주자!

플레이어의 HealthSystem에 damageClip을 넣어주자!

0개의 댓글