20231220_AudioSource

2023. 12. 21. 07:43IT/TIL

오늘의 TIL은 팀 프로젝트를 진행하면서 배웠던 유니티에서 사용하는 AudioSource와 관련된 내용이다.

 

유니티에서 소리를 재생할 수 있게 해주는 방법으로 오디오 소스를 사용하는데,

오디오 소스는 재생하려고 하는 소리를 저장하고,

오디오 리스너 혹은 믹서는 소리를 재생하게 해주게 제공하고 있다.

 

Unity Documentation에 따르면 아래와 같이 정의하고 있다.

오디오 소스(Audio Source) 는 씬에서 오디오 클립을 재생합니다. 
이 클립은 오디오 리스너 또는 오디오 믹서를 통해 재생 가능합니다. 
오디오 소스는 모든 종류의 오디오 클립을 재생할 수 있으며, 
2D나 3D로, 또는 혼합(스페이셜 블렌드)하여 재생하도록 설정할 수 있습니다. 
오디오는 여러 스피커에 분배되거나(스테레오–7.1)(_ 스프레드), 
3D와 2D 사이에서 자연스럽게 모핑됩니다( 스페이셜 블렌드_). 
감쇠 커브를 통해 거리에 따라 제어할 수 있습니다. 
또한 리스너가 하나 이상의 리버브 존에 있을 경우 소스에 잔향이 적용됩니다. 
더 풍부한 음향감을 위해 각 오디오 소스에 개별 필터를 적용할 수 있습니다. 
자세한 내용은 오디오 효과를 참조하십시오.

 

 

 

Unity Documetation만 보면 조금은 복잡해보일 수 있지만,

실제로 사용해보면 아주 간단하게 소리를 재생할 수 있다.

우선 기본적으로 Main Camera에 Audio Listener가 Component로 연결되어 있다.

그리고 보통은 이 Main Camera는 플레이어 캐릭터를 따라가게 되므로,

캐릭터의 위치에서 소리가 재생되게 만들어주므로, BGM이나 효과음이 내 위치에서 들리게 된다.

따라서 다른 특별한 조작없이, Audio Source만 생성해주고 그 소리를 재생시켜주면 소리를 들을 수 있게 된다.

 

이후에 외부에서 구한 Sound 파일을 유니티 Project의 Asset에 드래그&드랍으로 넣어주면

유니티에서 자동으로 Vorbis 파일로 변환하여 리소스로 추가시켜준다.

아래 이미지에서 Resource 폴더 안에 Sound 폴더를 만들어서 파일들을 넣어주니

02.BGM ~ 08.Outro 까지 자동으로 파일이 변환되어 들어간 것을 볼 수 있다.

 

이러한 과정을 거치게되면 리소스는 완성된 것으로,

C# 스크립트를 통해서 소리가 재생되게만 만들어주면 된다.

 

소리를 재생시켜주는 것은 보통은 SoundManager 혹은 AudioManager 등의 Manager로 사용하는데,

Manager를 사용한다는 것은 싱글톤을 이용하겠다는 느낌이다.

즉, 소리와 관련해서는 하나의 싱글톤을 가지는 매니저를 만들고, 그 매니저를 통해서

원하는 위치에서 소리를 플레이해주는 것이 간편한 방법이다.

 

이번 프로젝트에서 사용했던 SoundManager를 예시로 들면 아래와 같은 코드를 사용했는데,

더보기
public class SoundManager : MonoBehaviour
{
    public static SoundManager instance;

    public float BGMVolume = 0.2f;
    public float EffectVolume = 0.6f;
    public float DoorVolume = 0.4f;

    public AudioClip[] soundEffects;
    public AudioClip bgmClip;

    [HideInInspector] public AudioSource audioSource;
    [HideInInspector] public AudioSource bgmAudioSource;
    [HideInInspector] public AudioSource outroAudioSource;
    [HideInInspector] public AudioSource trapAudioSource;


    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(gameObject);
            return;
        }

        audioSource = gameObject.AddComponent<AudioSource>();
        bgmAudioSource = gameObject.AddComponent<AudioSource>();
        outroAudioSource = gameObject.AddComponent<AudioSource>();
        trapAudioSource = gameObject.AddComponent<AudioSource>();
    }

    private void Start()
    {
        PlayBGM();
    }

    public void PlayBGM()
    {
        bgmAudioSource.clip = bgmClip;
        bgmAudioSource.loop = true;
        bgmAudioSource.volume = BGMVolume;
        bgmAudioSource.Play();
    }

    public void PlayWalkEffect()
    {
        if (!audioSource.isPlaying)
        {
            audioSource.PlayOneShot(soundEffects[0], EffectVolume);
        }
    }

    public void PlayDoorLockEffect()
    {
        audioSource.PlayOneShot(soundEffects[1], DoorVolume);
    }

    public void PlayDoorOpenEffect()
    {
        audioSource.PlayOneShot(soundEffects[2], DoorVolume);
    }

    public void PlayInteractionEffect()
    {
        audioSource.PlayOneShot(soundEffects[3], DoorVolume);
    }
    public void PlaytrapEffect()
    {
        trapAudioSource.PlayOneShot(soundEffects[4], EffectVolume);
    }

    public void PlayOutroEffect()
    {
        outroAudioSource.PlayOneShot(soundEffects[5], BGMVolume);
    }
}

 

이 코드를 위에서부터 살펴보면,

public class SoundManager : MonoBehaviour
{
    public static SoundManager instance;

    public float BGMVolume = 0.2f;
    public float EffectVolume = 0.6f;
    public float DoorVolume = 0.4f;

    public AudioClip[] soundEffects;
    public AudioClip bgmClip;

    [HideInInspector] public AudioSource audioSource;
    [HideInInspector] public AudioSource bgmAudioSource;
    [HideInInspector] public AudioSource outroAudioSource;
    [HideInInspector] public AudioSource trapAudioSource;


    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(gameObject);
            return;
        }

        audioSource = gameObject.AddComponent<AudioSource>();
        bgmAudioSource = gameObject.AddComponent<AudioSource>();
        outroAudioSource = gameObject.AddComponent<AudioSource>();
        trapAudioSource = gameObject.AddComponent<AudioSource>();
    }

 

우선 

public static SoundManaager instance 부분과

Awake()의 if, else 문으로

SoundManager를 싱글톤화 해주고

 

이 SoundManager가 알아야될 것(각 volume의 수치들, AudioClip 배열과 AudioSource들)을 연결해주는데,

AudioClip은 유니티 Inspector 창에서 연결해주고,

(이 부분에서 Inspector 창에서 Sound Effects 부분에 03.WalkEffect ~ 08.Outro 까지 넣어주고,

Bgm Clip은 따로 넣어주게 만들었다)

 

AudioSource는 Awake의 audioSource = gameObject.AddComponenet<AudioSource>();

로 스크립터로 연결해주게 하였다.

 

이후에 아래의 코드가 있는데,

private void Start()
{
    PlayBGM();
}

public void PlayBGM()
{
    bgmAudioSource.clip = bgmClip;
    bgmAudioSource.loop = true;
    bgmAudioSource.volume = BGMVolume;
    bgmAudioSource.Play();
}

public void PlayWalkEffect()
{
    if (!audioSource.isPlaying)
    {
        audioSource.PlayOneShot(soundEffects[0], EffectVolume);
    }
}

public void PlayDoorLockEffect()
{
    audioSource.PlayOneShot(soundEffects[1], DoorVolume);
}

 

시작 시에 자동으로 BGM을 계속해서 재생시키기 위해

bgmAudioSource.loop = true; 라고 설정해주고,

bgmAudioSource.Play(); 라는 기능을 사용해서 BGM을 재생시킬 수 있는데,

이 BGM를 다른 곳에서도 사용할 수 있기에 PlayBGM()이라는 함수를 만들어서 작동하도록 하였다.

 

또, PlayWalkEffect() 라는 함수에서는 특이한 점이

if 문을 사용하고 있다는 점인데, 이는 플레이어가 움직이는 경우에는 발소리가 나지만,

멈추는 경우 발소리를 멈추게하려고 만든 기능이다.

또, PlayOneShot 함수는 작동 시에 해당하는 audioSource를 한 번 재생하는 기능을 갖고 있는데,

audioSource.PlayOneShot(auidoSource, Volume)

처럼 audioSource 뒤에 Volume을 넣어줌으로써 음량을 조절할 수 있다.

 

이후에 나머지 함수들은 같은 함수들인데 PlayDoorLockEffect()만 설명하면,

PlayWalkEffect()와 같은 방식이지만,

if문 없이 작동하므로 이 소리는 한 번만 끝까지 재생되게 만들었다.

 

이후에 싱글톤화 시킨 이 함수들을 원하는 곳에서

SoundManager.instance.함수명(); 으로 바로 사용할 수 있다.

'IT > TIL' 카테고리의 다른 글

20231222_NavMesh  (0) 2023.12.23
20231221_팀 프로젝트 회고  (0) 2023.12.22
20231219_CherryPickCommit  (0) 2023.12.21
20231218_OnTrigger,OnCollision  (0) 2023.12.19
20231215_데이터 저장  (0) 2023.12.16