[Unity][2D-Game] Undead Survivor (15)

suhan0304·2023년 11월 12일
0

유니티 - Undead Survivor

목록 보기
19/21
post-thumbnail

Review

  • 캐릭터 해금 시스템을 구현했다.
  • Lock된 버튼과 Unlock된 버튼을 따로 만들어 업적 달성에 따라 활성화를 해 해금을 표현했다.
  • 간단한 업적 저장 데이터는 PlayerPrefs에 저장해서 유지시켰따.
  • 업적 달성 시 오른쪽 위에 알람이 뜨도록 Notice 또한 구현했다.

강의영상 (15) - 편리한 오디오 시스템 구축


개발

유니티의 오디오

AudioManager 오브젝르를 생성후 오디오 파일을 컴포넌트로 넣으면 AuidoSource라는 컴포넌트가 추가된다.

  • Plater On Wake : 활성화 되어 있으면 최초 1회 자동 재생

AudioClip : 재생시킬 실제 오디오 에셋
AudioSource : 에셋인 AudioClip을 재생시켜주는 컴포넌트
AudioListener : 장면에서 재생 중인 오디오를 듣는 컴포넌트

  • AudioListener은 메인 카메라의 컴포넌트

위 세가지 구성요소가 있어야 실제로 유니티에서 오디오를 사용할 수 있다. 이 외에도 다양한 오디오 필터 컴포넌트를 사용할 수 있다.


오디오 매니저

이제 오디오를 관리할 AudioManager 스크리트를 작성한다. 이때 효과음은 여러 효과음을 동시 다발적으로 낼 수 있도록 채널을 여러개 만들어 플레이어를 여러개 사용할 수 있도록 선언한다.

AudioManager.cs

public class AudioManager : MonoBehaviour
{
    public static AudioManager instance;

    [Header("#BGM")] //배경음
    public AudioClip bgmClip;   //클립
    public float bgmVolume;     //볼륨
    AudioSource bgmPlayer;      //플레이어(오디오소스)

    [Header("#SFX")] //효과음
    public AudioClip[] sfxClip;     //클립
    public float sfxVolume;         //볼륨
    public int channels;            //채널 개수
    AudioSource[] sfxPlayers;        //플레이어(오디오소스)
    int channelIndex;               //재생 중인 채널 인덱스

    private void Awake()
    {
        instance = this;
        Init(); //초기화 진행
    }

    void Init()
    {
        //배경음 플레이어 초기화
        GameObject bgmObject = new GameObject("BgmPlayer");
        bgmObject.transform.parent = transform;
        //AddComponent로 함수로 오디오소스를 생성하고 변수에 저장
        bgmPlayer = bgmObject.AddComponent<AudioSource>();
        bgmPlayer.playOnAwake = false;  //자동 1회 재생 off
        bgmPlayer.loop = true;          //자동 반복 on
        bgmPlayer.volume = bgmVolume;   //볼륨 설정
        bgmPlayer.clip = bgmClip;       //AudioClip 설정

        //효과음 플레이어 초기화
        GameObject sfxObject = new GameObject("SfxPlayer");
        sfxObject.transform.parent = transform;
        sfxPlayers = new AudioSource[channels];  //채널 수만큼 오디오소스 초기화
        
        //sfxPlayers 안에 오디오소스 하나씩 추가해주면서 각 오디오소스 마다 설정 초기화
        for(int i=0;i<sfxPlayers.Length;i++)
        {
            sfxPlayers[i] = sfxObject.AddComponent<AudioSource>();
            sfxPlayers[i].playOnAwake = false;  //자동 반복 off
            sfxPlayers[i].volume = sfxVolume;   //볼륨 설정
        }
    }

}

이제 bgm 볼륨을 0.2, sfx 볼륨을 0.5, 16채널로 인스펙터에서 설정한다. 실행하면 자동으로 BgmPlayer와 SfxPlayer가 생성되는 것을 확인할 수 있다.


효과음 시스템

이제 오디오매니저 인스펙터를 잠굼하고 모든 효과음 파일을 배열 변수의 이름에 드래그 드랍해서 넣어준다.

sfx 효과음들을 쉽게 사용할 수 있도록 오디오 매니저 안에 아래와 같이 열거형 선언

AudioManager.cs

//효과음과 1:1 대응하는 열거형 데이터 선언
public enum Sfx
{
    //열거형 데이터는 대응하는 숫자를 정해줄 수 있다. 
    //그 이후 데이터는 알아서 +1씩 되면서 진행된다.
    Dead, Hit, LevelUp=3, Lose, Melle, Range=7, Select, Win
}

이제 채널 인덱스 변수를 활용해서 현재 사용중인 채널을 한바퀴 돌면서 확인하도록 로직을 구현한다.

public void PlaySfx(Sfx sfx)
{
    //플레이어에 sfx 인덱스 넣어주고 재생
    for(int i=0;i<sfxPlayers.Length;i++)
    {
        //채널 개수만큼 순회하도록 채널인덱스 변수 활용
        int loopIndex = (i + channelIndex) % sfxPlayers.Length;

        //재생 중인 플레이어는 continue 시켜버린다.
        if (sfxPlayers[i].isPlaying)
            continue;

        //사운드가 2개 이상있을 경우 랜덤 재생
        int ranIndex = 0;
        if (sfx == Sfx.Hit || sfx == Sfx.Melee) {
            ranIndex = Random.Range(0, 2);
            }

        channelIndex = loopIndex;
        sfxPlayers[loopIndex].clip = sfxClips[(int)sfx + ranIndex];
        sfxPlayers[loopIndex].Play();
        break;
    }
}

이제 효과음을 사용하는 곳에서 playSfx 함수를 호출해서 사용해보자. enum으로 선언해놓았으니 Ctrl + Space로 sfx 열거형의 Select를 가져다가 쓰면 오타 없이 사용할 수 있다.

  • 게임 매니저의 GameStart
    AudioManager.instance.PlaySfx(AudioManager.Sfx.Select);

  • 게임 매니저의 GameOverRoutine
    AudioManager.instance.PlaySfx(AudioManager.Sfx.Lose);

  • 게임 매니저의 GameVictoryRoutine
    AudioManager.instance.PlaySfx(AudioManager.Sfx.Win);

  • 업적 매니저의 NoticeRoutine
    AudioManager.instance.PlaySfx(AudioManager.Sfx.LevelUp);

  • LevelUp 스크립트의 Show
    AudioManager.instance.PlaySfx(AudioManager.Sfx.LevelUp);

  • LevelUp 스크립트의 Hide
    AudioManager.instance.PlaySfx(AudioManager.Sfx.Select);

  • Weapon 스크립트의 Fire
    AudioManager.instance.PlaySfx(AudioManager.Sfx.Range);

  • Enemy 스크립트의 OnTriggerEnter2D
    AudioManager.instance.PlaySfx(AudioManager.Sfx.Hit);
    AudioManager.instance.PlaySfx(AudioManager.Sfx.Dead);
    - 마지막에 EnemyCleaner에는 Dead소리가 발생하지 않도록 아래와 같이 작성

if(GameManager.Instance.isLive)
	AudioManager.instance.PlaySfx(AudioManager.Sfx.Dead);

배경음 시스템

이제 배경음을 넣어주자. 아래 영상을 참고해서 BGM 파일을 하나 다운받아주자. 나는 참고 링크의 BGM을 사용했다.

무료 에셋 사운드 파일을 찾고 싶다면 아래 영상을 참고하자

이제 BGM 파일을 Audio 폴더 안에 넣어주고 인스펙터의 BGM Clip에 드래그드랍해서 추가해준다.

AudioManager.cs

public void PlayBgm(bool isPlay)
{
    if(isPlay)
    {
        bgmPlayer.Play();
    }
    else
    {
        bgmPlayer.Stop();
    }
} 
  • 게임 매니저의 GameStart
    AudioManager.instance.PlayBgm(true);
  • 게임 매니저의 GameOver
  • 게임 매니저의 GameVictory
    AudioManager.instance.PlayBgm(false);

레벨업창이 떴을때 오디오 필터를 사용해서 레벨업 창이 떠 있을때는 오디오에 효과를 넣어보자.
Main 카메라에 Audio High Pass Filter 컴포넌트를 추가해준 후 비활성화 해준다.

AudioMager.cs

AudioHighPassFilter bgmEffect;  //브금효과

void Init() {
	~~(생략)~~
    
	bgmEffect = Camera.main.GetComponent<AudioHighPassFilter>();
}

public void EffectBgm(bool isPlay)
{
    bgmEffect.enabled = isPlay;
}

메인 카메라 접급은 Camera 클래스를 사용하면 간편하게 갈 수 있다.

이제 레벨업 스크립트의 Show와 Hide에서 EffectBgm을 호출해서 레벨업 UI가 나타날 때 필터를 켜고 사라지면 끄도록 함수를 호출한다.

이 때 효과음은 적용받지 않도록 sfxPlayer의 오디오소스의 Bypass Listener Effects 속성을 활성화 시켜주어야한다. 따라서 오디오 매니저의 sfxPlayer을 생성해주는 부분에서 해당 속성을 활성화 시켜준다.

AudioManager.cs - Init()

sfxPlayers[i] = sfxObject.AddComponent<AudioSource>();
sfxPlayers[i].playOnAwake = false;  //자동 반복 off
sfxPlayers[i].bypassListenerEffects = true; //Effect 영향 안받게 설정
sfxPlayers[i].volume = sfxVolume;   //볼륨 설정

Audio HighPass Filter는 Listener Effect 계열


결과물

gif 파일은 소리가 나지 않는다.
..

profile
Be Honest, Be Harder, Be Stronger

0개의 댓글